Android应用程序线程消息循环模型分析(4)
接下来我们再看看应用程序的配置文件AndroidManifest.xml: <?xmlversion="1.0"encoding="utf-8"?> <manifestxmlns:android="http://schemas.android.com/apk/res/android" package="shy.luo.counter" android:versionCode="1" android:versionName="1.0"> <applicationandroid:icon="@drawable/icon"android:label="@string/app_name"> <activityandroid:name=".Counter" android:label="@string/app_name"> <intent-filter> <actionandroid:name="android.intent.action.MAIN"/> <categoryandroid:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest> 这个配置文件很简单,我们就不介绍了。 再来看应用程序的界面文件,它定义在res/layout/main.xml文件中: <?xmlversion="1.0"encoding="utf-8"?> <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" android:gravity="center"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginBottom="10px" android:orientation="horizontal" android:gravity="center"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="4px" android:gravity="center" android:text="@string/counter"> </TextView> <TextView android:id="@+id/textview_counter" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="0"> </TextView> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:gravity="center"> <Button android:id="@+id/button_start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="@string/start"> </Button> <Button android:id="@+id/button_stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="@string/stop"> </Button> </LinearLayout> </LinearLayout> 这个界面配置文件也很简单,等一下我们在模拟器把这个应用程序启动起来后,就可以看到它的截图了。 应用程序用到的字符串资源文件位于res/values/strings.xml文件中: <?xmlversion="1.0"encoding="utf-8"?> <resources> <stringname="app_name">Counter</string> <stringname="counter">Counter:</string> <stringname="start">StartCounter</string> <stringname="stop">StopCounter</string> </resources> 最后,我们还要在工程目录下放置一个编译脚本文件Android.mk: LOCAL_PATH:=$(callmy-dir) include$(CLEAR_VARS) LOCAL_MODULE_TAGS:=optional LOCAL_SRC_FILES:=$(callall-subdir-java-files) LOCAL_PACKAGE_NAME:=Counter include$(BUILD_PACKAGE) 接下来就要编译了。有关如何单独编译Android源代码工程的模块,以及如何打包system.img,请参考 如何单独编译Android源代码中的模块 一文。 执行以下命令进行编译和打包: USER-NAME@MACHINE-NAME:~/Android$mmmpackages/experimental/Counter USER-NAME@MACHINE-NAME:~/Android$makesnod 这样,打包好的Android系统镜像文件system.img就包含我们前面创建的Counter应用程序了。 再接下来,就是运行模拟器来运行我们的例子了。关于如何在Android源代码工程中运行模拟器,请参考 在Ubuntu上下载、编译和安装Android最新源代码 一文。 执行以下命令启动模拟器: USER-NAME@MACHINE-NAME:~/Android$emulator 最后我们就可以在Launcher中找到Counter应用程序图标,把它启动起来,点击Start按钮,就会看到应用程序界面上的计数器跑起来了: 这样,使用AsyncTask的例子就介绍完了,下面,我们就要根据上面对AsyncTask的使用情况来重点分析它的实现了。 AsyncTask类定义在frameworks/base/core/java/android/os/AsyncTask.java文件中: publicabstractclassAsyncTask<Params,Progress,Result>{ ...... privatestaticfinalBlockingQueue<Runnable>sWorkQueue= newLinkedBlockingQueue<Runnable>(10); privatestaticfinalThreadFactorysThreadFactory=newThreadFactory(){ privatefinalAtomicIntegermCount=newAtomicInteger(1); publicThreadnewThread(Runnabler){ returnnewThread(r,"AsyncTask#"+mCount.getAndIncrement()); } }; ...... privatestaticfinalThreadPoolExecutorsExecutor=newThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE,KEEP_ALIVE,TimeUnit.SECONDS,sWorkQueue,sThreadFactory); privatestaticfinalintMESSAGE_POST_RESULT=0x1; privatestaticfinalintMESSAGE_POST_PROGRESS=0x2; privatestaticfinalintMESSAGE_POST_CANCEL=0x3; privatestaticfinalInternalHandlersHandler=newInternalHandler(); privatefinalWorkerRunnable<Params,Result>mWorker; privatefinalFutureTask<Result>mFuture; ...... publicAsyncTask(){ mWorker=newWorkerRunnable<Params,Result>(){ publicResultcall()throwsException{ ...... returndoInBackground(mParams); } }; mFuture=newFutureTask<Result>(mWorker){ @Override protectedvoiddone(){ Messagemessage; Resultresult=null; try{ result=get(); }catch(InterruptedExceptione){ android.util.Log.w(LOG_TAG,e); }catch(ExecutionExceptione){ thrownewRuntimeException("AnerroroccuredwhileexecutingdoInBackground()", e.getCause()); }catch(CancellationExceptione){ message=sHandler.obtainMessage(MESSAGE_POST_CANCEL, newAsyncTaskResult<Result>(AsyncTask.this,(Result[])null)); message.sendToTarget(); return; }catch(Throwablet){ thrownewRuntimeException("Anerroroccuredwhileexecuting" +"doInBackground()",t); } message=sHandler.obtainMessage(MESSAGE_POST_RESULT, newAsyncTaskResult<Result>(AsyncTask.this,result)); message.sendToTarget(); } }; } ...... publicfinalResultget()throwsInterruptedException,ExecutionException{ returnmFuture.get(); } ...... publicfinalAsyncTask<Params,Progress,Result>execute(Params...params){ ...... mWorker.mParams=params; sExecutor.execute(mFuture); returnthis; } ...... protectedfinalvoidpublishProgress(Progress...values){ sHandler.obtainMessage(MESSAGE_POST_PROGRESS, newAsyncTaskResult<Progress>(this,values)).sendToTarget(); } privatevoidfinish(Resultresult){ ...... onPostExecute(result); ...... } ...... privatestaticclassInternalHandlerextendsHandler{ @SuppressWarnings({"unchecked","RawUseOfParameterizedType"}) @Override publicvoidhandleMessage(Messagemsg){ AsyncTaskResultresult=(AsyncTaskResult)msg.obj; switch(msg.what){ caseMESSAGE_POST_RESULT: //Thereisonlyoneresult result.mTask.finish(result.mData[0]); break; caseMESSAGE_POST_PROGRESS: result.mTask.onProgressUpdate(result.mData); break; caseMESSAGE_POST_CANCEL: result.mTask.onCancelled(); break; } } } privatestaticabstractclassWorkerRunnable<Params,Result>implementsCallable<Result>{ Params[]mParams; } privatestaticclassAsyncTaskResult<Data>{ finalAsyncTaskmTask; finalData[]mData; AsyncTaskResult(AsyncTasktask,Data...data){ mTask=task; mData=data; } } } 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966885,如需转载请自行联系原作者