package com.shizhefei.mvchelper.testcase;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.ViewHolder;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.shizhefei.mvc.IAsyncDataSource;
import com.shizhefei.mvc.IDataSource;
import com.shizhefei.mvc.testcase.R;
import com.shizhefei.mvchelper.testcase.TestCaseData.IParamValuesNotify;
import com.shizhefei.recyclerview.HFAdapter;
import com.shizhefei.recyclerview.HFAdapter.OnItemClickListener;
import com.shizhefei.task.Code;
import com.shizhefei.task.IAsyncTask;
import com.shizhefei.task.ICallback;
import com.shizhefei.task.ITask;
import com.shizhefei.task.TaskHelper;
import com.shizhefei.task.imp.SimpleCallback;
import com.shizhefei.utils.ArrayListMap;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public abstract class ABSTestCaseFragment extends Fragment {
private LinearLayout paramsRecyclerView;
private TextView resultTextView;
private Button runButton;
private Button resetButton;
private List<TestCaseData> datas;
private Gson gson;
private TasksAdapter tasksAdapter;
private RecyclerView recyclerView;
private View itemRunButton;
private LayoutInflater inflater;
private TextView resultStateTextView;
private ArrayListMap<String, ParamLine> lines = new ArrayListMap<String, ParamLine>();
private TaskHelper<Object> taskHelper;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.inflater = inflater;
View view = inflater.inflate(R.layout.testcase, container, false);
taskHelper = new TaskHelper<>();
GsonBuilder builder = new GsonBuilder();
// 格式化输出
builder.setPrettyPrinting();
// builder.serializeNulls();
builder.addSerializationExclusionStrategy(new ExclusionStrategy() {
@Override
public boolean shouldSkipField(FieldAttributes f) {
// // 这里作判断,决定要不要排除该字段,return true为排除
// if ("finalField".equals(f.getName())) return true; //按字段名排除
// Expose expose = f.getAnnotation(Expose.class);
// if (expose != null && expose.deserialize() == false) return
// true; //按注解排除
return false;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
// 直接排除某个类 ,return true为排除
return clazz == Gson.class || clazz == Bitmap.class;
}
}).create();
gson = builder.create();
recyclerView = (RecyclerView) view.findViewById(R.id.testcase2_recyclerView);
paramsRecyclerView = (LinearLayout) view.findViewById(R.id.testcase2_params_recyclerView);
resultTextView = (TextView) view.findViewById(R.id.testcase2_result_textView);
runButton = (Button) view.findViewById(R.id.testcase2_run_button);
resetButton = (Button) view.findViewById(R.id.testcase2_reset_button);
itemRunButton = view.findViewById(R.id.testcase2_run2_button);
resultStateTextView = (TextView) view.findViewById(R.id.testcase2_resultState_textView);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(tasksAdapter = new TasksAdapter());
// recyclerView.addItemDecoration(new DividerItemDecoration(getContext()));
//
// // paramsRecyclerView.setLayoutManager(new
// // LinearLayoutManager(getContext()));
// // paramsRecyclerView.addItemDecoration(new
// // DividerItemDecoration(getContext()));
// // paramsRecyclerView.setAdapter(paramsAdapter = new ParamsAdapter());
datas = getTestCaseDatas();
resetButton.setOnClickListener(onClickListener);
runButton.setOnClickListener(onClickListener);
itemRunButton.setOnClickListener(onClickListener);
tasksAdapter.setOnItemClickListener(onItemClickListener);
resultTextView.setOnClickListener(onClickListener);
updateRight();
return view;
}
private void updateRight() {
TestCaseData data = datas.get(selectPosition);
// paramsRecyclerView.setText(param(data));
resultTextView.setText(data.result);
switch (data.status) {
case -1:
resultStateTextView.setText("ERROR");
break;
case 0:
resultStateTextView.setText("");
break;
case 1:
resultStateTextView.setText("RUNING");
break;
case 2:
resultStateTextView.setText("SUCCESS");
break;
}
// paramsAdapter.notifyDataSetChanged();
tasksAdapter.notifyDataSetChangedHF();
String json;
json = gson.toJson(data.task);
map2 = gson.fromJson(json, map2.getClass());
Object task = data.task;
Object object = task;
for (ParamLine line : lines.values()) {
line.cancel();
}
lines.clear();
paramsRecyclerView.removeAllViews();
for (int i = 0; i < map2.size(); i++) {
ParamLine paramLine = new ParamLine();
View itemView = inflater.inflate(R.layout.testcase_param_item, paramsRecyclerView, false);
paramsRecyclerView.addView(itemView);
paramLine.itemView = itemView;
paramLine.keyTextView = (TextView) itemView.findViewById(R.id.textView1);
paramLine.valueEditText = (EditText) itemView.findViewById(R.id.editText1);
paramLine.valueGetButton = (Button) itemView.findViewById(R.id.testcase_param_item_paramGet_button);
Object value = map2.valueAt(i);
String key = map2.keyAt(i);
paramLine.key = key;
paramLine.keyTextView.setText(key);
paramLine.valueEditText.removeTextChangedListener(paramLine.textWatcher);
paramLine.valueEditText.setText(String.valueOf(value));
paramLine.valueEditText.addTextChangedListener(paramLine.textWatcher);
paramLine.valueGetButton.setOnClickListener(paramLine.onClickListener);
boolean has = false;
if (data.paramGets.containsKey(key)) {
has = true;
paramLine.paramGetTask = data.paramGets.get(key);
}
if (!has) {
out:
for (Entry<String[], IAsyncTask<Map<String, String>>> entry : data.paramGetsMap.entrySet()) {
for (String param : entry.getKey()) {
if (param.equals(key)) {
has = true;
paramLine.paramGetTaskMap = entry.getValue();
break out;
}
}
}
}
if (has) {
paramLine.valueGetButton.setVisibility(View.VISIBLE);
} else {
paramLine.valueGetButton.setVisibility(View.GONE);
}
try {
Field field = object.getClass().getDeclaredField(key);
field.setAccessible(true);
paramLine.field = field;
} catch (Exception e) {
e.printStackTrace();
}
lines.put(key, paramLine);
}
}
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (v == runButton) {
TestCaseData data = datas.get(0);
exe(0, data, true);
} else if (v == resetButton) {
taskHelper.cancelAll();
datas = getTestCaseDatas();
tasksAdapter.notifyDataSetChanged();
updateRight();
} else if (v == itemRunButton) {
hideSoftKeyboard(itemRunButton);
updateTastParams();
exe(selectPosition, datas.get(selectPosition), false);
} else if (v == resultTextView) {
if (resultTextView.getText().length() == 0) {
return;
}
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setItems(new String[]{"复制", "分享", "全屏"}, new AlertDialog.OnClickListener() {
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onClick(DialogInterface dialog, int which) {
String text = resultTextView.getText().toString();
if (which == 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
ClipboardManager cmb = (ClipboardManager) getContext().getSystemService(Context.CLIPBOARD_SERVICE);
cmb.setText(text);
} else {
android.text.ClipboardManager manager = (android.text.ClipboardManager) getContext().getSystemService(
Context.CLIPBOARD_SERVICE);
manager.setText(text);
}
Toast.makeText(getContext(), "复制成功", Toast.LENGTH_SHORT).show();
} else if (which == 1) {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain"); // 纯文本
intent.putExtra(Intent.EXTRA_TEXT, text);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(Intent.createChooser(intent, "分享"));
} else {
final Dialog dialog2 = new Dialog(getActivity(), R.style.testCase_dialog);
dialog2.getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
dialog2.setContentView(R.layout.testcase_fullscreen);
TextView textView = (TextView) dialog2.findViewById(R.id.testcase2_fullsreen_result_textView);
textView.setText(resultTextView.getText());
dialog2.show();
WindowManager.LayoutParams params = dialog2.getWindow().getAttributes();
params.width = WindowManager.LayoutParams.MATCH_PARENT;
params.height = WindowManager.LayoutParams.MATCH_PARENT;
dialog2.getWindow().setAttributes(params);
}
}
});
builder.show();
}
}
};
protected abstract List<TestCaseData> getTestCaseDatas();
private int selectPosition = 0;
private OnItemClickListener onItemClickListener = new OnItemClickListener() {
@Override
public void onItemClick(HFAdapter adapter, ViewHolder vh, int position) {
selectPosition = position;
updateRight();
}
};
private ArrayListMap<String, Object> map2 = new ArrayListMap<String, Object>();
private void updateTastParams() {
TestCaseData testCaseData = datas.get(selectPosition);
Object task = testCaseData.task;
Object object = task;
for (Entry<String, Object> data : map2.entrySet()) {
try {
Field field = object.getClass().getDeclaredField(data.getKey());
field.setAccessible(true);
field.set(object, data.getValue());
} catch (Exception e) {
e.printStackTrace();
}
}
testCaseData.task = task;
}
private class ParamLine {
public Field field;
protected View itemView;
private TextView keyTextView;
private EditText valueEditText;
private String key;
private Button valueGetButton;
private IAsyncTask<String> paramGetTask;
private IAsyncTask<Map<String, String>> paramGetTaskMap;
public void cancel() {
taskHelper.cancel(paramGetTask);
taskHelper.cancel(paramGetTaskMap);
}
public void setValue(String value) {
valueEditText.removeTextChangedListener(textWatcher);
valueEditText.setText(value);
valueEditText.addTextChangedListener(textWatcher);
updateParam();
}
private TextWatcher textWatcher = new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
updateParam();
}
};
private void updateParam() {
try {
String text = valueEditText.getText().toString();
Object newValue;
if (String.class.equals(field.getType())) {
newValue = text;
} else {
newValue = gson.fromJson(text, field.getType());
}
map2.put(key, newValue);
} catch (Exception e) {
e.printStackTrace();
}
}
private OnClickListener onClickListener = new OnClickListener() {
@Override
public void onClick(View v) {
if (v == valueGetButton) {
if (paramGetTask != null) {
if (paramGetTask instanceof IParamValuesNotify) {
IParamValuesNotify getParamTask = (IParamValuesNotify) paramGetTask;
getParamTask.notifyCurrentParamValues(map2, v);
}
taskHelper.execute(paramGetTask, new SimpleCallback<String>() {
@Override
public void onPostExecute(Object task, Code code, Exception exception, String success) {
switch (code) {
case SUCCESS:
valueGetButton.setText("获取");
valueEditText.setText(success);
break;
case EXCEPTION:
Toast.makeText(getContext(), exception.getMessage(), Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
});
} else if (paramGetTaskMap != null) {
if (paramGetTask instanceof IParamValuesNotify) {
IParamValuesNotify getParamTask = (IParamValuesNotify) paramGetTask;
getParamTask.notifyCurrentParamValues(map2, v);
}
taskHelper.execute(paramGetTaskMap, new SimpleCallback<Map<String, String>>() {
@Override
public void onPostExecute(Object task, Code code, Exception exception, Map<String, String> success) {
switch (code) {
case SUCCESS:
valueGetButton.setText("获取");
for (Entry<String, String> testCaseData : success.entrySet()) {
ParamLine paramLine = lines.get(testCaseData.getKey());
if (paramLine != null) {
paramLine.setValue(testCaseData.getValue());
}
}
break;
case EXCEPTION:
Toast.makeText(getContext(), exception.getMessage(), Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
});
}
}
}
};
}
private class TasksAdapter extends HFAdapter {
@Override
public ViewHolder onCreateViewHolderHF(ViewGroup viewGroup, int type) {
return new ItemViewHolder(inflater.inflate(R.layout.testcase_item, viewGroup, false));
}
@Override
public void onBindViewHolderHF(ViewHolder vh, int position) {
ItemViewHolder holder = (ItemViewHolder) vh;
holder.setData(position, datas.get(position));
}
@Override
public int getItemCountHF() {
return datas.size();
}
class ItemViewHolder extends ViewHolder {
private Button b;
private TestCaseData data;
private int index;
public ItemViewHolder(View itemView) {
super(itemView);
}
private void setData(int index, TestCaseData data) {
this.index = index;
this.data = data;
TextView textView = (TextView) itemView.findViewById(R.id.item_testcase2_textView);
View stateView = itemView.findViewById(R.id.item_testcase2_state_view);
if (index == selectPosition) {
itemView.setBackgroundColor(Color.WHITE);
} else {
itemView.setBackgroundColor(Color.parseColor("#cccccc"));
}
switch (data.status) {
case -1:
stateView.setBackgroundColor(Color.RED);
break;
case 0:
stateView.setBackgroundColor(Color.TRANSPARENT);
break;
case 1:
stateView.setBackgroundResource(R.drawable.testcase_arrow);
break;
case 2:
stateView.setBackgroundColor(Color.GREEN);
break;
}
textView.setText(data.text);
}
}
}
private void exe(int index, TestCaseData data, boolean exeNext) {
taskHelper.cancelAll();
if (data.task instanceof IAsyncTask) {
taskHelper.execute((IAsyncTask) data.task, new MyCallBack(index, data, exeNext));
} else if (data.task instanceof ITask) {
taskHelper.execute((ITask) data.task, new MyCallBack(index, data, exeNext));
} else if (data.task instanceof IDataSource) {
taskHelper.execute((IDataSource) data.task, new MyCallBack(index, data, exeNext));
} else {
taskHelper.execute((IAsyncDataSource) data.task, new MyCallBack(index, data, exeNext));
}
}
public class MyCallBack<DATA> implements ICallback<Object> {
private int index = 0;
private TestCaseData data;
private boolean exeNext;
private long startTime;
public MyCallBack(int index, TestCaseData data, boolean exeNext) {
this.index = index;
this.data = data;
this.exeNext = exeNext;
}
public String getStackTraceString(Throwable e) {
if (e == null) {
return "";
}
StringWriter localStringWriter = new StringWriter();
PrintWriter localPrintWriter = new PrintWriter(localStringWriter);
e.printStackTrace(localPrintWriter);
return localStringWriter.toString();
}
@Override
public void onPreExecute(Object task) {
data.status = 1;
data.result = "";
tasksAdapter.notifyDataSetChanged();
updateRight();
startTime = SystemClock.uptimeMillis();
}
@Override
public void onProgress(Object task, int percent, long current, long total, Object extraData) {
}
@Override
public void onPostExecute(Object task, Code code, Exception exception, Object success) {
long time = SystemClock.uptimeMillis() - startTime;
String ttt = "执行耗时:" + time + "毫秒 \n\n" + data.result;
switch (code) {
case SUCCESS:
data.status = 2;
data.result = gson.toJson(success);
break;
case EXCEPTION:
data.status = -1;
data.result = getStackTraceString(exception);
break;
default:
if (TextUtils.isEmpty(data.result)) {
data.status = 0;
}
break;
}
data.result = ttt+data.result;
tasksAdapter.notifyDataSetChanged();
updateRight();
if (code != Code.CANCEL) {
if (exeNext) {
if (index + 1 < datas.size()) {
TestCaseData newData = datas.get(index + 1);
exe(index + 1, newData, true);
}
}
}
}
}
/**
* 隐藏软键盘
*/
public static void hideSoftKeyboard(View mEt) {
((InputMethodManager) mEt.getContext().getSystemService(Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(mEt.getWindowToken(), 0);
}
}