标签:
注:该文章翻译自Ali Muzaffar的文章《8 ways to do asynchronous processing in Android and counting》
Android提供了许多API来支持异步处理的功能,结合着Java提供的方法和你手上拥有的,估计目前已经有数十种进行异步任务的方法。
AsyncTask
1 new AsyncTask<URL, Integer, Long>() { 2 protected Long doInBackground(URL... urls) { 3 int count = urls.length; 4 long totalSize = 0; 5 for (int i = 0; i < count; i++) { 6 totalSize += Downloader.downloadFile(urls[i]); 7 publishProgress((int) ((i / (float) count) * 100)); 8 // Escape early if cancel() is called 9 if (isCancelled()) break; 10 } 11 return totalSize; 12 } 13 14 protected void onProgressUpdate(Integer... progress) { 15 setProgressPercent(progress[0]); 16 } 17 18 protected void onPostExecute(Long result) { 19 showDialog("Downloaded " + result + " bytes"); 20 } 21 }.execute(url1, url2, url3); 22 // Modified Code from google Android API
1 public class RSSPullService extends IntentService { 2 @Override 3 protected void onHandleIntent(Intent workIntent) { 4 // Gets data from the incoming Intent 5 String dataString = workIntent.getDataString(); 6 ... 7 // Do work here, based on the contents of dataString 8 ... 9 } 10 }
1 // AndroidManifest.xml 2 <application 3 android:icon="@drawable/icon" 4 android:label="@string/app_name"> 5 ... 6 <!-- 7 Because android:exported is set to "false", 8 the service is only available to this app. 9 --> 10 <service 11 android:name=".RSSPullService" 12 android:exported="false"/> 13 ... 14 <application/>
1 JobInfo.Builder builder = new JobInfo.Builder(kJobId++, 2 mServiceComponent); 3 String delay = mDelayEditText.getText().toString(); 4 if (delay != null && !TextUtils.isEmpty(delay)) { 5 builder.setMinimumLatency(Long.valueOf(delay) * 1000); 6 } 7 String deadline = mDeadlineEditText.getText().toString(); 8 if (deadline != null && !TextUtils.isEmpty(deadline)) { 9 builder.setOverrideDeadline(Long.valueOf(deadline) * 1000); 10 } 11 boolean requiresUnmetered = 12 mWiFiConnectivityRadioButton.isChecked(); 13 boolean requiresAnyConnectivity = 14 .mAnyConnectivityRadioButton.isChecked(); 15 if (requiresUnmetered) { 16 builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_UNMETERED); 17 } else if (requiresAnyConnectivity) { 18 builder.setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY); 19 } 20 builder.setRequiresDeviceIdle(mRequiresIdleCheckbox.isChecked()); 21 builder.setRequiresCharging(mRequiresChargingCheckBox.isChecked());mTestService.scheduleJob(builder.build()); 22 // CANCEL JOBS 23 JobScheduler tm = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE); 24 tm.cancelAll();
CountDownTimer
1 new CountDownTimer() { 2 @Override 3 public void onFinish() { 4 } 5 @Override 6 public void onTick(long millisUntilFinished) { 7 } 8 }.start();
Java Threads or Android HandlerThread
1 new Thread(new Runnable(){ 2 public void run() { 3 // do something here 4 } 5 }).start();
Android的HandlerThread可以被用于在后台线程中handle Message。使用它会被消息处理机制限制,因为消息处理更倾向于重定向而不是处理任务,尽管这样也为我们提供了一个将一些任务放在后台进程运行的方法。一个使用HandlerThread的可行方法是在一个后台进程中运行一个服务。
1 public class TickTockService extends Service { 2 public void onCreate() { 3 // Start up the thread running the service. Note that we create a 4 // separate thread because the service normally runs in the process‘s 5 // main thread, which we don‘t want to block. We also make it 6 // background priority so CPU-intensive work will not disrupt our UI. 7 mThread = new HandlerThread("ServiceArguments", 8 Process.THREAD_PRIORITY_BACKGROUND); 9 mThread.start(); 10 // Get the HandlerThread‘s Looper and use it for our Handler 11 mServiceLooper = mThread.getLooper(); 12 mServiceHandler = new Handler(mServiceLooper); 13 } 14 }
FutureTask
FutureTask提供异步处理的功能,但是,当运算还没有结束或者是结果没有被准备好的时候调用get()方法会阻塞线程。
我居然在不少地方使用了FutureTask,例如:当你想要在谷歌的Volley中采用阻塞的方式执行请求的时候就可以用FutureTask。下面是如何使用FutrueTask的例子,在你使用FutureTask的时候你必须确保UI线程不会被阻塞。
1 RequestFuture<JSONObject> future = RequestFuture.newFuture(); 2 JsonObjectRequest request = new JsonObjectRequest(URL, null, future, future); 3 requestQueue.add(request);
1 try { 2 JSONObject response = future.get(); // this will block (forever) 3 } catch (InterruptedException e) { 4 // exception handling 5 } catch (ExecutionException e) { 6 // exception handling 7 } 8 Java Timer / ScheduledThreadPoolExecutor 9 10
下面是一个使用Java Timer的例子,功能是在5秒后做一些工作。它们两个类可以被用于调度一些运行于后台的线程。在Android中还有一些类似的处理方法,你可以使用带有postDelayed的Handler或者是Handler 结合调用sendMessageDelayed()方法,这样handler就会运行在后台正如上面展示的一样。同样,你要清楚这两个API对于Android的生命周期不清楚,很难在Activity、Fragment或者是View中引用它们,因为这样可能会导致内存泄露。
1 Timer timer = new Timer(); 2 timer.schedule(new TimerTask(){ 3 public void run() { 4 // time ran out. 5 timer.cancel(); 6 } 7 }, 5000);
Java API中的解释:ThreadPoolExecutor可以通过延迟执行或者是定期执行来调度进程。该类在许多工作线程需要被创建、或者是需要ThreadPoolExecutor更加的可扩展和可用的时候比Timer类更加适用。延迟任务的执行不会早于它们被创建,但是关于它们何时可用并不提供实时性的保证。任务被安排了近乎相同的执行时间,并且采用先进先出(FIFO)的机制来调度子任务。
1 public class CustomScheduledExecutor extends ScheduledThreadPoolExecutor { 2 static class CustomTask<V> implements RunnableScheduledFuture<V> { ... } 3 protected <V> RunnableScheduledFuture<V> decorateTask( 4 Runnable r, RunnableScheduledFuture<V> task) { 5 return new CustomTask<V>(r, task); 6 } 7 protected <V> RunnableScheduledFuture<V> decorateTask( 8 Callable<V> c, RunnableScheduledFuture<V> task) { 9 return new CustomTask<V>(c, task); 10 } 11 // ... add constructors, etc. 12 } 13 // Code from Java API
在Android中使用ScheduledThreadPoolExecutor会如同Timer和Java的Threads一样遇到相同的问题:如果你需要更行UI界面,你需要使用Handler来发送消息给UI线程,或者是通过一个Listener来传递。ScheduledThreadPoolExecutor是Java的一部分,它同样对于Activity、Fragment的生命周期不明感,因此大量的Listener需要被手动地清理或者是换,否则很有可能会导致内存泄露。
标签:
原文地址:http://www.cnblogs.com/xlk0101/p/5122432.html