Android Framework系列之IPC(一)

tcxingdechen 2011-04-18

说到Android的IPC(Inter-ProcessConmmunication)首先想到的就是Handler和Looper,Handler用于多进程之间的通信和数据交换,将各进程之间通信的数据Message放置到MessageQueue里,而Looper用于创建各进程自身的messagequeue,然后在适当的时候分发给相应的进程。

我们知道在Android中,每一个UI线程是一个主线程(MainThread),Android为每一个主线程维护一个MessageQueue,当用户需要长时间的背景线程操作的时候,需要create自己的newthread,这样的newthread是没有自己的messagequeue的,只能共享主线程的messagequeue并且将所做的运算结果和数据通过Handler发送到主线程的messagequeue里,被主线程共享。

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"

>

<ProgressBar

android:id="@+id/ProgressBar01"

android:layout_width="150dip"

android:layout_height="wrap_content"

style="?android:attr/progressBarStyleHorizontal">

</ProgressBar>

</LinearLayout>

这个xml文件创建了一个progressbar,并且将style设置成水平,

style="?android:attr/progressBarStyleHorizontal

Xml代码

<?xmlversion="1.0"encoding="utf-8"?>

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="waterlife.ipc.demo"

android:versionCode="1"

android:versionname="1.0">

<applicationandroid:icon="@drawable/icon"android:label="@string/app_name">

<activityandroid:name=".IPCConmunication"

android:label="@string/app_name">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

</application>

<uses-permissionandroid:name="android.permission.INTERNET"/>

</manifest>

为了访问网络,需要在manifestfile里设置accessinternet的permission,

<uses-permissionandroid:name="android.permission.INTERNET"/>

Java代码

packagewaterlife.ipc.demo;

importjava.io.InputStream;

importjava.net.MalformedURLException;

importjava.net.URL;

importjava.net.URLConnection;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.os.Handler;

importandroid.os.HandlerThread;

importandroid.os.Looper;

importandroid.os.Message;

importandroid.widget.ProgressBar;

publicclassIPCConmunicationextendsActivity{

staticProgressBarpb;

finalintUPDATE_PROGRESS_BAR=1000;

/**Calledwhentheactivityisfirstcreated.*/

@Override

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

pb=(ProgressBar)findViewById(R.id.ProgressBar01);

Downloaddl=newDownload();

newThread(dl).start();

}

HandlermHandle=newHandler()

{

publicvoidhandleMessage(Messagemsg)

{

switch(msg.what)

{

caseUPDATE_PROGRESS_BAR:

pb.setProgress(msg.arg1);

break;

default:

break;

}

}

};

classDownloadimplementsRunnable

{

@Override

publicvoidrun(){

inttotalSize=0;

InputStreamrecevier=null;

try{

URLmyUrl=newURL("http://bbs.nju.edu.cn");

URLConnectionurlConn=myUrl.openConnection();

totalSize=urlConn.getContentLength();

recevier=urlConn.getInputStream();

byte[]b=newbyte[256];

intlength=0;

length+=recevier.read(b);

while(length<totalSize)

{

Messagemsg=mHandle.obtainMessage(UPDATE_PROGRESS_BAR);

msg.arg1=(int)(length*100/totalSize);

if(mHandle.hasMessages(UPDATE_PROGRESS_BAR))

{

mHandle.removeMessages(UPDATE_PROGRESS_BAR);

}

mHandle.sendMessage(msg);

length+=recevier.read(b);

Thread.sleep(1000);//睡眠1S,这个方法是不值得推荐的,因为它会使线程独占CPU,在以后的例子会使用更加有效的方法

}

recevier.close();

}catch(MalformedURLExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}catch(Exceptionex)

{

ex.printStackTrace();

}

}

}

}

我们create出来的一个newthread,用这个线程去网络上下载数据包,并且把下载的进度更新到UI主线程的progressbar上。两个线程之间的通信是用Handler来传递的。在这里新的线程Download和UImainthread共用messagequeue。

当然,我们可以为自己新建的线程设置自身的messagequeue,方法如下:

Java代码

packagewaterlife.ipc.demo;

importjava.io.InputStream;

importjava.net.MalformedURLException;

importjava.net.URL;

importjava.net.URLConnection;

importandroid.app.Activity;

importandroid.os.Bundle;

importandroid.os.Handler;

importandroid.os.HandlerThread;

importandroid.os.Looper;

importandroid.os.Message;

importandroid.widget.ProgressBar;

publicclassIPCConmunicationextendsActivity{

staticProgressBarpb;

finalintUPDATE_PROGRESS_BAR=1000;

/**Calledwhentheactivityisfirstcreated.*/

@Override

publicvoidonCreate(BundlesavedInstanceState){

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

pb=(ProgressBar)findViewById(R.id.ProgressBar01);

Downloaddl=newDownload();

newThread(dl).start();

}

classDownloadimplementsRunnable

{

@Override

publicvoidrun(){

inttotalSize=0;

InputStreamrecevier=null;

HandlerThreadthreadLoop=newHandlerThread("Download");

threadLoop.start();

LoopermLooper=threadLoop.getLooper();

HandlermHandle=newHandler(mLooper)

{

publicvoidhandleMessage(Messagemsg)

{

switch(msg.what)

{

caseUPDATE_PROGRESS_BAR:

pb.setProgress(msg.arg1);

break;

default:

break;

}

}

};

try{

URLmyUrl=newURL("http://bbs.nju.edu.cn");

URLConnectionurlConn=myUrl.openConnection();

totalSize=urlConn.getContentLength();

recevier=urlConn.getInputStream();

byte[]b=newbyte[256];

intlength=0;

length+=recevier.read(b);

while(length<totalSize)

{

Messagemsg=mHandle.obtainMessage(UPDATE_PROGRESS_BAR);

msg.arg1=(int)(length*100/totalSize);

if(mHandle.hasMessages(UPDATE_PROGRESS_BAR))

{

mHandle.removeMessages(UPDATE_PROGRESS_BAR);

}

mHandle.sendMessage(msg);

length+=recevier.read(b);

Thread.sleep(1000);

}

recevier.close();

}catch(MalformedURLExceptione){

//TODOAuto-generatedcatchblock

e.printStackTrace();

}catch(Exceptionex)

{

ex.printStackTrace();

}

}

}

}

HandlerThread是一个专门用于新建Looper的线程类,它实现了Looper.prepare()和Looper.loop()的方法。HandlerThreadceate一个新的Looper并且绑定到新线程的Handler上,实现了对新线程创建自己的Messagequeue的目的。

相关推荐