Android Framework系列之IPC(一)

原创文章,转载请标注出处----

 

说到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 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 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" />

 

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,方法如下:

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的目的。

你可能感兴趣的:(thread,多线程,android,.net,OS)