最近在尝试在app里对接百度ai的相关图片试别的api,发现网络请求是无法写在主线程中的(网路请求还需要申请权限),主要原因大致和主线程为了保护ui控件的正常使用而生成的一种保护机制。
1.Handler消息传递机制
public class MainActivity4Handler extends AppCompatActivity {
private TextView tv;
//事件更新器
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (msg.what == 0x123) {
//符合条件,更新控件
tv.setText("更新后的TextView:" + (String) msg.obj);
}
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new MyThread().start();// 启动一个新线程
}
class MyThread extends Thread {
@Override
public void run() {
//异步处理事件
//延迟两秒更新
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//传递消息(只传递一个数字)
//handler.sendEmptyMessage(0x123);
//传递一个message对象
Message message = new Message();
String x = "ssss";
message.what = 0x123;
message.obj = x;//这里可以传json字符串
handler.sendMessage(message);
}
}
}
2. 使用AsyncTask异步任务
public class MainActivity4Async extends AppCompatActivity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new Yibu().execute(tv);//执行异步
}
//泛型参数分别代表,传入,中间,返回值
class Yibu extends AsyncTask<TextView, String, String>{
//预处理,可以随意提示一些信息
@Override
protected void onPreExecute() {
Toast.makeText(MainActivity4Async.this, "这里是预处理", Toast.LENGTH_SHORT).show();
}
//调用publishProgress()方法后,该方法会很快执行,利用方法中携带的参数进行对界面进行刷新
@Override
protected void onProgressUpdate(String... values) {
for (int i = 0; i < values.length; i++) {
tv.setText(values[i]);
}
}
//执行后台程序
@Override
protected String doInBackground(TextView... views) {
//比如耗时多的联网操作等
TextView tv = views[0];
tv.setText("中途更新");
publishProgress("string 字符串,可以是json格式,用来传递执行完成后的结果");
return null;
}
//后台任务执行完毕后,可以通过此方法进行提示
@Override
protected void onPostExecute(String s) {
Toast.makeText(MainActivity4Async.this, "处理完成", Toast.LENGTH_SHORT).show();
}
}
}
3. 使用runOnUiThread(action)方法
public class MainAc4UiThread extends AppCompatActivity {
private TextView tv;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
new MyThread().start();//必须在Activity中实现
}
class MyThread extends Thread {
@Override
public void run() {
//写这个方法,表示新开的ui更新线程
runOnUiThread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
//延迟两秒更新
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
tv.setText("更新后的TextView");
}
});
}
}
}
4. 使用Handler的post(Runnabel r)方法
这个没什么特别的,核心代码块。
Handler handler = new Handler();
handler.post(new Runnable(){
@Override
public void run() {
try {
//延迟两秒更新
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
tv.setText("更新后的TextView");
}
综合四种用法,个人还是喜欢使用使用第二种,生命周期很清楚,同时也是官方提供的一种方法,也便于实现代码的分离,在异步使用不多的情况下推荐使用。
最后更新一下,理解了以上四种原理后推荐使用RxAndroid框架,具体的文章可以参阅https://www.jianshu.com/p/1cad42c4bc04
可以省下大量的代码量。
网友评论