方法一: view.post(Runnable action)
假如该方法是在子线程中
textView.post(new Runnable() {
@Override
public void run() {
textView.setText("更新textView");
imageView.setBackgroundResource(R.drawable.update);
}
});
这是view自带的方法,比较简单,如果你的子线程里可以得到要更新的view的话,可以用此方法进行更新。
view还有一个方法view.postDelayed(Runnable action, long delayMillis)用来延迟发送。
方法二: activity.runOnUiThread(Runnable action)
假如该方法是在子线程中
注意:context 对象要是 主线程中的MainActivity,这样强转才可以。
public void updateUI(final Context context) {
((MainActivity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
}
});
}
如果没有上下文(context),试试下面的方法:
1.用view.getContext()可以得到上下文。
2.跳过context直接用new Activity().runOnUiThread(Runnable action)来切换到主线程。
方法三: Handler机制
首先在主线程中定义Handler,Handler mainHandler = new Handler();(必须要在主线程中定义才能操作主线程,如果想在其他地方定义声明时要这样写Handler mainHandler = new Handler(Looper.getMainLooper()),来获取主线程的 Looper 和 Queue )
获取到 Handler 后就很简单了,用handler.post(Runnable r)方法把消息处理放在该 handler 依附的消息队列中(也就是主线程消息队列)。
(1):假如该方法是在子线程中
Handler mainHandler = new Handler(Looper.getMainLooper());
mainHandler.post(new Runnable() {
@Override
public void run() {
}
});
Handler还有下面的方法:
1.postAtTime(Runnable r, long uptimeMillis); //在某一时刻发送消息
2.postAtDelayed(Runnable r, long delayMillis); //延迟delayMillis毫秒再发送消息
(2): 假设在主线程中
Handler myHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
case 0:
break;
case 1:
break;
default:
break;
}
}
}
之后可以把 mainHandler 当做参数传递在各个类之间,当需要更新UI时,可以调用sendMessage一系列方法来执行handleMessage里的操作。
假设现在在子线程了
Message msg = myHandler.obtainMessage();
msg.what = 0;
myHandler.sendMessage(msg);
如上代码,只是发送了个消息标识,并没有传其他参数。
如果想传递参数,可以这样:
msg.what = 1;
msg.arg1=2;
msg.arg2=3;
Bundle bundle=new Bundle();
bundle.putString("dd","adfasd");
bundle.putInt("love",5);
msg.setData(bundle);
msg.obj=bundle;
myHandler.sendMessage(msg);
总结: msg.obj它的功能比较强大一下,至于它和利用Bundle传递数据,那个会效率高一些,更节省内存一些。个人认为:从传递数据的复杂程度看,由简单到复杂依次使用,arg1, setData(), obj。会比较好一些。
当然可以用简化方法sendEmptyMessage(int what)来减少不必要的代码,这样写:
myHandler.sendEmptyMessage(0);
发送消息的其他方法有:
endEmptyMessageAtTime(int what, long uptimeMillis);
sendEmptyMessageDelayed(int what, long delayMillis);
sendMessageAtTime(Message msg, long uptimeMillis);
sendMessageDelayed(Message msg, long delayMillis);
sendMessageAtFrontOfQueue(Message msg);
方法四: 使用AsyncTask
private class MyAsyncTask extends AsyncTask<String, Integer, String> {
@Override
protected void onPreExecute() {
super.onPreExecute();
System.out.println("MyAsyncTask.onPreExecute");
}
@Override
protected String doInBackground(String... params) {
System.out.println("MyAsyncTask.doInBackground");
int count = 0;
for (int i = 0; i < 10; i++) {
try {
count++;
publishProgress((count % 100) * 10);
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return "耗时操作执行完毕";
}
@Override
protected void onProgressUpdate(Integer... values) {
super.onProgressUpdate(values);
progressBar.setProgress(values[0]);
textView.setText("loading..." + values[0] + "%");
System.out.println("MyAsyncTask.onProgressUpdate");
}
@Override
protected void onPostExecute(String aVoid) {
super.onPostExecute(aVoid);
System.out.println("MyAsyncTask.onPostExecute aVoid=" + aVoid);
textView.setText(aVoid);
}
@Override
protected void onCancelled() {
super.onCancelled();
System.out.println("MyAsyncTask.onCancelled");
progressBar.setProgress(0);
textView.setText("0");
}
@Override
protected void onCancelled(String s) {
super.onCancelled(s);
}
}
注意:doInBackground方法是在子线程中,所以,我们在这个方法里面执行耗时操作。同时,由于其返回结果会传递到onPostExecute方法中,而onPostExecute方法工作在UI线程,这样我们就在这个方法里面更新ui,达到了异步更新ui的目的。
对于android的异步加载数据及更新ui,我们不仅可以选择AsyncTask异步任务,还可以选择许多开源的网络框架,如: 点击进入了解更多 xUtils3,AsyncHttpClient,Okhttp,Volley,…,
这些优秀的网络框架让我们异步更新ui变得非常简单,而且,效率和性能也非常高。当然这些网络框架绝不仅仅就这么个功能,异步更新UI这只是他们的冰山一角!