记录一下bug,卡了半天,最后是gpt给出的方法。
bug
2023-11-02 13:23:44.227 20096-20134 成功 com.miao.myapplicationdemo04 E {
"code":"200",
"data":"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCQk33iNdA8Iey7J6XrBsidqn6u8EDLWPHsfEUgLQ3qiTikhPKDTzZkpAfU/O0x6NvSKa7Dp0+uqWT3vnW1De0+3u8mCYdVfOdH94VG4xg5U5UrRJei8HhPiXuvKQ+6NBtebCCW5adZ4pBgOiU14cJLhVmm+dYiLo3IDD5LqrlomQIDAQAB",
"msg":"成功"
}
2023-11-02 13:23:44.374 20096-20134 AndroidRuntime com.miao.myapplicationdemo04 E FATAL EXCEPTION: OkHttp Dispatcher
Process: com.miao.myapplicationdemo04, PID: 20096
java.lang.RuntimeException: Can't create handler inside thread Thread[OkHttp http://121.40.169.166:8989/...,5,main] that has not called Looper.prepare()
at android.os.Handler.<init>(Handler.java:205)
at android.os.Handler.<init>(Handler.java:118)
at android.view.textservice.SpellCheckerSession$1.<init>(SpellCheckerSession.java:106)
at android.view.textservice.SpellCheckerSession.<init>(SpellCheckerSession.java:106)
at android.view.textservice.TextServicesManager.newSpellCheckerSession(TextServicesManager.java:181)
at android.widget.SpellChecker.resetSession(SpellChecker.java:127)
at android.widget.SpellChecker.setLocale(SpellChecker.java:148)
at android.widget.SpellChecker.spellCheck(SpellChecker.java:223)
at android.widget.Editor.updateSpellCheckSpans(Editor.java:788)
at android.widget.Editor.sendOnTextChanged(Editor.java:1359)
at android.widget.TextView.sendOnTextChanged(TextView.java:9758)
at android.widget.TextView.setText(TextView.java:5733)
at android.widget.TextView.setText(TextView.java:5571)
at android.widget.EditText.setText(EditText.java:122)
at android.widget.TextView.setText(TextView.java:5528)
at com.miao.myapplicationdemo04.core.http.OkhttpActivity$3.onResponse(OkhttpActivity.java:79)
at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:764)
2023-11-02 13:23:44.568 20096-20134 Process com.miao.myapplicationdemo04 I Sending signal. PID: 20096 SIG: 9
2023-11-02 13:23:44.727 1954-2047 InputDispatcher system_server E channel 'b940c49 com.miao.myapplicationdemo04/com.miao.myapplicationdemo04.core.http.OkhttpActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
问题
发送get请求后,数据可以正常显示,但是应用很快闪退。
看一下源码:
public class OkhttpActivity extends AppCompatActivity {
private String url = "http://121.40.169.166:8989/rsapks";
private EditText tvRes;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.okhttp_layout);
tvRes = findViewById(R.id.et_res);
findViewById(R.id.btn_get).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
get();
}
});
findViewById(R.id.btn_post).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
post();
}
});
}
/**
* 异步get请求
*/
private void get() {
//第一步获取okHttpClient对象
OkHttpClient client = new OkHttpClient.Builder()
.build();
//第二步构建Request对象
Request request = new Request.Builder()
.url(url)
.get()
.build();
//第三步构建Call对象
Call call = client.newCall(request);
//第四步:异步get请求
call.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
// Log.i("ttit", e.getMessage());
Log.i("错误", e.getMessage());
}
// @Override
// public void onResponse(Call call, Response response) throws IOException {
// //得到的子线程
// String result = response.body().string();
// Log.e("成功", result);
// tvRes.setText(result);
// }
@Override
public void onResponse(Call call, Response response) throws IOException {
// 得到的子线程
final String result = response.body().string();
Log.e("成功", result);
runOnUiThread(new Runnable() {
@Override
public void run() {
tvRes.setText(result);
}
});
}
});
}
其中
总结:
法一:
因为试图在非UI线程中更新UI元素,这是不被允许的,因为Android要求UI操作必须在主线程中执行。在你的代码中,tvRes.setText(result)
尝试在onResponse
回调的子线程中执行,导致了闪退。
使用 runOnUiThread
方法,可以像这样修改 onResponse
回调:
@Override
public void onResponse(Call call, Response response) throws IOException {
// 得到的子线程
final String result = response.body().string();
Log.e("成功", result);
runOnUiThread(new Runnable() {
@Override
public void run() {
tvRes.setText(result);
}
});
}
这将确保 tvRes.setText(result)
在主线程上执行,而不会导致闪退。
法二:
可以使用 Handler
来实现相同的目标。在OkhttpActivity
中,可以声明一个 Handler
对象,然后在 onResponse
中使用它来发送消息来更新UI
private Handler handler = new Handler(Looper.getMainLooper());
@Override
public void onResponse(Call call, Response response) throws IOException {
// 得到的子线程
final String result = response.body().string();
Log.e("成功", result);
handler.post(new Runnable() {
@Override
public void run() {
tvRes.setText(result);
}
});
}