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

我们知道在Android中,每一个UI线程是一个主线程(Main Thread),Android为每一个主线程维护一个Message Queue,当用户需要长时间的背景线程操作的时候,需要create自己的new thread,这样的new thread是没有自己的message queue的,只能共享主线程的message queue并且将所做的运算结果和数据通过Handler发送到主线程的message queue里,被主线程共享。
Xml代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns: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代码
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="waterlife.ipc.demo"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".IPCConmunication"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

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

</manifest>
为了访问网络,需要在manifest file里设置access internet的permission,
<uses-permission android:name="android.permission.INTERNET" />

Java代码
package waterlife.ipc.demo;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.widget.ProgressBar;


public class IPCConmunication extends Activity {
static ProgressBar pb;
final int UPDATE_PROGRESS_BAR = 1000;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pb = (ProgressBar)findViewById(R.id.ProgressBar01);
Download dl = new Download();
new Thread(dl).start();

}


Handler mHandle = new Handler()
{
public void handleMessage(Message msg)
{
switch(msg.what)
{
case UPDATE_PROGRESS_BAR:
pb.setProgress(msg.arg1);
break;
default:
break;
}
}
};

class Download implements Runnable
{

@Override
public void run() {
int totalSize = 0;
InputStream recevier = null;

try {
URL myUrl = new URL("http://bbs.nju.edu.cn");

URLConnection urlConn = myUrl.openConnection();
totalSize = urlConn.getContentLength();
recevier = urlConn.getInputStream();
byte[] b =new byte[256];
int length = 0;
length += recevier.read(b);
while(length < totalSize)
{
Message msg = 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 (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (Exception ex)
{
ex.printStackTrace();
}
}
}
}

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

当然,我们可以为自己新建的线程设置自身的message queue,方法如下:
Java代码
package waterlife.ipc.demo;

import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.widget.ProgressBar;


public class IPCConmunication extends Activity {
static ProgressBar pb;
final int UPDATE_PROGRESS_BAR = 1000;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
pb = (ProgressBar)findViewById(R.id.ProgressBar01);
Download dl = new Download();
new Thread(dl).start();

}


class Download implements Runnable
{

@Override
public void run() {
int totalSize = 0;
InputStream recevier = null;

HandlerThread threadLoop = new HandlerThread("Download");
threadLoop.start();
Looper mLooper = threadLoop.getLooper();
Handler mHandle = new Handler(mLooper)
{
public void handleMessage(Message msg)
{
switch(msg.what)
{
case UPDATE_PROGRESS_BAR:
pb.setProgress(msg.arg1);
break;
default:
break;
}
}
};

try {
URL myUrl = new URL("http://bbs.nju.edu.cn");

URLConnection urlConn = myUrl.openConnection();
totalSize = urlConn.getContentLength();
recevier = urlConn.getInputStream();
byte[] b =new byte[256];
int length = 0;
length += recevier.read(b);
while(length < totalSize)
{
Message msg = 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 (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}catch (Exception ex)
{
ex.printStackTrace();
}
}
}
}

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

更多相关文章

  1. 浅析android通过jni控制service服务程序的简易流程
  2. 浅析Android中的消息机制-解决:Only the original thread that cr
  3. Android异步消息机制之Handler
  4. Android的Handler机制详解3_Looper.looper()不会卡死主线程
  5. Android之Handler用法总结
  6. Android开发之消息处理机制(一)——Handler
  7. 2011年Android(安卓)Camera学习笔记之一
  8. Android异步加载图像小结 (含线程池,缓存方法)
  9. android 面试题集

随机推荐

  1. JavaCV & Android
  2. Android 文件夹命名规范 国际化资源
  3. Android脚本环境
  4. Android中设置搜素联系人的布局
  5. Android版本号对应API、版本名称、NDK版
  6. android studio 各种问题 应该能帮助到你
  7. 最近总结的android疑惑(三)
  8. android xml中设置自适应图片
  9. 换掉整个程序的bitton样式,以及button的父
  10. android Manifest.xml选项(转贴)