15.Android 异步更新UI 技巧
Handler消息传递
private TextView handlerTV;
private static final int HANDLER_SUCCESS = 206;
private static class RefreshHandler extends Handler {
private final WeakReference<RefreshUIActivity> mActivity;
public RefreshHandler(RefreshUIActivity activity) {
mActivity = new WeakReference<>(activity);
}
/**
* Subclasses must implement this to receive messages.
*
* @param msg
*/
@Override
public void handleMessage(Message msg) {
RefreshUIActivity activity = this.mActivity.get();
if (activity != null) {
switch (msg.what) {
case HANDLER_SUCCESS: {
activity.handlerTV.setText("success");
break;
}
}
}
}
}
private final RefreshHandler refreshHandler = new RefreshHandler(RefreshUIActivity.this);
private final Runnable mRunnable = new Runnable() {
@Override
public void run() {
Message message = RefreshUIActivity.this.refreshHandler.obtainMessage();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
message.what = HANDLER_SUCCESS;
refreshHandler.sendMessageDelayed(message, 2000);
}
};
private final Thread mThread = new Thread(mRunnable);
this.mThread.start();
AsyncTask异步任务
对AsyncTask原理不熟悉的,可以看看Android AsyncTask 技巧。
private TextView asyncTaskTV;
public class MAsyncTask extends AsyncTask<String, Integer, String> {
private TextView textview;
public MAsyncTask(TextView textview) {
super();
this.textview = textview;
}
/**
* 对应AsyncTask第一个参数
* 异步操作,不在主UI线程中,不能对控件进行修改
* 可以调用publishProgress方法中转到onProgressUpdate(这里完成了一个handler.sendMessage(...)的过程)
*
* @param params The parameters of the task.
* @return A result, defined by the subclass of this task.
* @see #onPreExecute()
* @see #onPostExecute
* @see #publishProgress
*/
@Override
protected String doInBackground(String... params) {
int i = 0;
for (; i < 100; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.publishProgress(i);
}
return i + params[0];
}
/**
* 对应AsyncTask第二个参数
* 在doInBackground方法当中,每次调用publishProgress方法都会中转(handler.sendMessage(...))到onProgressUpdate
* 在主UI线程中,可以对控件进行修改
*
* @param values The values indicating progress.
* @see #publishProgress
* @see #doInBackground
*/
@Override
protected void onProgressUpdate(Integer... values) {
int value = values[0];
this.textview.setText(value+"%");
}
/**
* 对应AsyncTask第三个参数 (接受doInBackground的返回值)
* 在doInBackground方法执行结束之后在运行,此时已经回来主UI线程当中 能对UI控件进行修改
*
* @param s The result of the operation computed by {@link #doInBackground}.
* @see #onPreExecute
* @see #doInBackground
* @see #onCancelled(Object)
*/
@Override
protected void onPostExecute(String s) {
this.textview.setText("执行结束:" + s);
}
/**
* 运行在主UI线程中,此时是预执行状态,下一步是doInBackground
*
* @see #onPostExecute
* @see #doInBackground
*/
@Override
protected void onPreExecute() {
super.onPreExecute();
}
/**
* <p>Applications should preferably override {@link #onCancelled(Object)}.
* This method is invoked by the default implementation of
* {@link #onCancelled(Object)}.</p>
* <p/>
* <p>Runs on the UI thread after {@link #cancel(boolean)} is invoked and
* {@link #doInBackground(Object[])} has finished.</p>
*
* @see #onCancelled(Object)
* @see #cancel(boolean)
* @see #isCancelled()
*/
@Override
protected void onCancelled() {
super.onCancelled();
}
}
MAsyncTask mAsyncTask = new MAsyncTask(this.asyncTaskTV);
mAsyncTask.execute("%");
Handler post
Handler.post(Runnabel r)的原理:也就是调用了Handler.sendMessageDelayed(…)
Handler post 源码
/**
* Causes the Runnable r to be added to the message queue.
* The runnable will be run on the thread to which this handler is
* attached.
*
* @param r The Runnable that will be executed.
*
* @return Returns true if the Runnable was successfully placed in to the
* message queue. Returns false on failure, usually because the
* looper processing the message queue is exiting.
*/
public final boolean post(Runnable r)
{
return sendMessageDelayed(getPostMessage(r), 0);
}
Handler post模板
private TextView postHandlerTV;
private final Runnable postRunnable = new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
RefreshUIActivity.this.postHandlerTV.setText("Handler.post(...)");
}
};
Handler postHandler = new Handler();
postHandler.post(this.postRunnable);
Activity runOnUiThread
Activity.runOnUiThread(Runnable r)原理:如果是主UI线程,则直接调用post(Runnable r)方法,交给post()去处理线程,不是主UI线程则执行Runnable.start。
Activity runOnUiThread 源码
/**
* Runs the specified action on the UI thread. If the current thread is the UI
* thread, then the action is executed immediately. If the current thread is
* not the UI thread, the action is posted to the event queue of the UI thread.
*
* @param action the action to run on the UI thread
*/
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
Activity runOnUiThread 模板
private TextView runOnUiThreadTV;
private final Runnable uiRunnable = new Runnable() {
@Override
public void run() {
RefreshUIActivity.this.runOnUiThreadTV.setText("success");
}
};
private class MThread extends Thread{
/**
* Calls the <code>run()</code> method of the Runnable object the receiver
* holds. If no Runnable is set, does nothing.
*
* @see Thread#start
*/
@Override
public void run() {
RefreshUIActivity.this.runOnUiThread(RefreshUIActivity.this.uiRunnable);
}
}
private final MThread runThread = new MThread();
this.runThread.start();