由来
希望在代码的任何地方,无论是在Ui线程中调用,还是Thread中调用,都能指定Runnable执行的所在的线程池。
Codes
package com.example.androidbackgroundexecuter; import java.util.concurrent.Executor; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.MessageQueue; /** * * @author Zheng Haibo * @Web http://www.mobctrl.net * */ public final class GlobalExecutor implements Executor { static final String APP_EXECUTOR = "APP_EXECUTER"; private final Handler mainHandler; private final Handler backgroundHandler; public GlobalExecutor() { if (!isOnMainThread()) { throw new IllegalStateException( "Error!Please init the Executor in the main thread..."); } mainHandler = new Handler(Looper.getMainLooper()); HandlerThread handlerThread = new HandlerThread(APP_EXECUTOR); handlerThread.start(); backgroundHandler = new Handler(handlerThread.getLooper()); } @Override public void execute(final Runnable command) { executeInBackground(command, 0); } /** * execute the command in background thread with a delay of {@link #delay} * * @param command */ public void execute(final Runnable command, int delay) { executeInBackground(command, delay); } /** * execute the command in UiThread * * @param command */ public void executeInUiThread(final Runnable command) { mainHandler.post(command); } /** * execute the command in main thread with a delay of {@link #delay} * * @param command */ public void executeInUiThread(final Runnable command, int delay) { mainHandler.postDelayed(command, delay); } /** * execute the command in background thread with a delay of {@link #delay} * * @param command */ public void executeInBackground(final Runnable command, final int delay) { if (isOnMainThread()) { executeDelayedAfterIdleUnsafe(command, delay); } else { mainHandler.post(new Runnable() { @Override public void run() { executeDelayedAfterIdleUnsafe(command, delay); } }); } } /** * execute the command in background thread * * @param command */ public void executeInBackground(final Runnable command) { executeInBackground(command, 0); } private boolean isOnMainThread() { return Looper.getMainLooper().getThread() == Thread.currentThread(); } private void executeDelayedAfterIdleUnsafe(final Runnable task, final int delay) { Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() { @Override public boolean queueIdle() { backgroundHandler.postDelayed(task, delay); return false; } }); } }
注意,new GlobalExecutor()是需要在主线程。
使用举例
package com.example.androidbackgroundexecuter; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.os.Process; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private GlobalExecutor mGlobalExecutor = null; private Button btn1; private Button btn2; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGlobalExecutor = new GlobalExecutor(); btn1 = (Button) findViewById(R.id.btn_1); btn1.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { System.out.println("debug:btn 1 click"); btn1.setBackgroundColor(Color.BLACK); mGlobalExecutor.execute(new Runnable() { @Override public void run() { System.out.println("debug:click1 execute tid = " + Process.myTid() + ",pid=" + Process.myPid()); } }); mGlobalExecutor.executeInUiThread(new Runnable() { @Override public void run() { System.out .println("debug: click1 executeInUiThread tid = " + Process.myTid() + ",pid=" + Process.myPid()); } }); } }); btn2 = (Button) findViewById(R.id.btn_2); btn2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { System.out.println("debug:btn 2 click"); new Thread(new Runnable() { @Override public void run() { System.out.println("debug: click2(run) tid = " + Process.myTid() + ",pid=" + Process.myPid()); mGlobalExecutor.execute(new Runnable() { @Override public void run() { System.out .println("debug: click2 run execute in thread- tid = " + Process.myTid() + ",pid=" + Process.myPid()); } }); mGlobalExecutor .executeInUiThread(new Runnable() { @Override public void run() { System.out .println("debug: click2 run execute in UiThread- tid = " + Process.myTid() + ",pid=" + Process.myPid()); btn1.setBackgroundColor(Color.RED); } }); } }).start(); } }); } }
相继点击按钮btn1和btn2,日志如下:
05-20 10:25:49.045: I/System.out(3144): debug:btn 1 click 05-20 10:25:49.115: I/System.out(3144): debug: click1 executeInUiThread tid = 3144,pid=3144 05-20 10:25:49.125: I/System.out(3144): debug:click1 execute tid = 3157,pid=3144 05-20 10:25:50.105: I/System.out(3144): debug:btn 2 click 05-20 10:25:50.105: I/System.out(3144): debug: click2(run) tid = 3582,pid=3144 05-20 10:25:50.145: I/System.out(3144): debug: click2 run execute in UiThread- tid = 3144,pid=3144 05-20 10:25:50.175: I/System.out(3144): debug: click2 run execute in thread- tid = 3157,pid=3144
优点
我们可以在任意线程中调用我们想执行的Runnable,非常方便。
更多交流
Android开发联盟QQ群:272209595