Thread中runOnUiThread的简单使用
16lz
2021-01-23
1.不能在主线程以外操作UI,android中把耗时的操作都放到子线程里面,主线程又叫UI线程
注意:
不要阻塞主线程(UI线程)
不要从主线程以外的线程更新UI(UI线程)
我们看看这个代码
public class FourActivity extends Activity { private Button btn; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_four); tv = (TextView) findViewById(R.id.tv_four); btn = (Button) findViewById(R.id.btn_four); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } Toast.makeText(getApplicationContext(), "click button", Toast.LENGTH_SHORT).show(); } }).start(); } }); }}
运行结果是:点击按钮,五秒之后,程序会错误闪退,错误日志为:
05-17 17:41:52.200 28847-28890/com.example.admin.ztest E/AndroidRuntime: FATAL EXCEPTION: Thread-2 Process: com.example.admin.ztest, PID: 28847 java.lang.RuntimeException: Can't toast on a thread that has not called Looper.prepare() at android.widget.Toast$TN.(Toast.java:397) at android.widget.Toast.(Toast.java:117) at android.widget.Toast.makeText(Toast.java:280) at android.widget.Toast.makeText(Toast.java:270) at com.example.admin.ztest.run.FourActivity$1$1.run(FourActivity.java:37) at java.lang.Thread.run(Thread.java:764)
2.使用runOnUiThread方法,我们修改一下程序:
package com.example.admin.ztest.run;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.example.admin.ztest.R;public class FourActivity2 extends Activity { private Button btn; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_four); tv = (TextView) findViewById(R.id.tv_four); btn = (Button) findViewById(R.id.btn_four); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "FourActivity2 click button", Toast.LENGTH_SHORT).show(); } }); } }).start(); } }); }}
这次程序运行正常,点击按钮,五秒以后,正确提示我们的内容。
在这种情况下,可以使用Activity的runOnUiThread方法将toast的显示发布到主线程。 从主线程调用时,runOnUiThread方法立即执行传递的操作,但是当从主线程以外调用时,它会将传递的操作发布到主线程的事件队列。
3.此外,还可以使用控件.post的方式,把消息传递到主线程中
package com.example.admin.ztest.run;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.example.admin.ztest.R;public class FourActivity3 extends Activity { private Button btn; private TextView tv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_four); tv = (TextView) findViewById(R.id.tv_four); btn = (Button) findViewById(R.id.btn_four); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } tv.post(new Runnable() { @Override public void run() { Toast.makeText(getApplicationContext(), "FourActivity3 click button", Toast.LENGTH_SHORT).show(); tv.setText("FourActivity3 click button"); } }); } }).start(); } }); }}
4.还有一种,最经典的方式,扩展性最好,使用最广泛的,就是Thread+Handler实现异步消息处理
package com.example.admin.ztest.run;import android.app.Activity;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.view.View;import android.widget.Button;import android.widget.TextView;import android.widget.Toast;import com.example.admin.ztest.R;public class FourActivity4 extends Activity { private Button btn; private TextView tv; //这个地方的handler最好封装 防止内存泄漏 private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 100) { String res = (String) msg.obj; tv.setText(res); Toast.makeText(getApplicationContext(), res, Toast.LENGTH_SHORT).show(); } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_four); tv = (TextView) findViewById(R.id.tv_four); btn = (Button) findViewById(R.id.btn_four); btn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); //模拟耗时操作,比如下载 } catch (InterruptedException e) { e.printStackTrace(); } Message msg = new Message(); msg.what = 100; //消息发送的标志 msg.obj = "FourActivity4 click button"; //消息发送的内容如: Object String 类 int handler.sendMessage(msg); } }).start(); } }); }}
更多相关文章
- 在Visual Studio 2010/2012/2013/2015上使用C#开发Android/IOS安
- Android framework源码按键操作的完整流程
- android 之 线程间的通信
- android通用文件操作