关闭

Android UI线程 HandlerThread 普通线程详解

275人阅读 评论(0) 收藏 举报
分类:

1.安卓的程序执行的入口UI主线程

     所有的Android应用程序组件——包括Activity、Service和Broadcast Receiver,都运行在主线程.因此,任何组件中的耗时操作都将阻塞其它的组件,包括Service和可见的Activity.

  使用后台线程,对于避免第2章中曾描述的“应用程序无响应ANR”对话框的情况是至关重要的.在Android中定义的无响应是指:Activity在5秒内不响应任何输入事件(例如一个按键事件)和Broadcast Receiver在10秒未完成onReceive的处理操作.

  不仅仅是你要避免这种情况,甚至是你都不应该能遇到这种情况.为耗时的处理使用后台线程,包括文件操作、网络搜索、数据库交互和复杂的计算.

2.Thread普通线程

执行耗时操作,避免ANR操作。


3.HandlerThread (重点分析)

a.内部源码实现

b.经典的demo实现,卸载sd卡服务

一.主界面Activity实现

package com.example.testhanlerthread;

import java.lang.reflect.Method;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.Message;
import android.os.SystemClock;
import android.os.storage.IMountService;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;


public class MainActivity extends Activity implements OnClickListener{
	
	
	  public TextView textview;
	  public Button handlerThreadBTN;   
	  HandlerThread handlerThread;  
	  
	  //作为全局变量进行消息的发放和接收到消息的处理
	  Handler handler;

	    @Override
		protected void onCreate(Bundle savedInstanceState) {
	    	
			super.onCreate(savedInstanceState);
			//打印UI线程的名称   
	        System.out.println("onCreate  CurrentThread = " + Thread.currentThread().getName());
	        
			setContentView(R.layout.activity_main);
			textview = (TextView) findViewById(R.id.textView1);
		    handlerThreadBTN = (Button) findViewById(R.id.handlerThreadBtn);
		    
		    handlerThreadBTN.setOnClickListener(this); 
			
			handlerThread = new HandlerThread("myHanler");  
	        handlerThread.start(); 
	        
	        //注意: 这里必须用到handler的这个构造器,因为需要把callback传进去
	        //从而使自己的HandlerThread的handlerMessage来替换掉Handler原生的handlerMessage,对注销的语句解释  
	        //handler = new Handler(handlerThread.getLooper(), handlerThread); 
	        handler = new Handler(handlerThread.getLooper()){
	        	
	        	public void formatSdcard(){
	        		//Phone path
	        		//String sDStateString="/mnt/sdcard";
	        		String sDStateString="/storage/sda1";  //ott path
	        		Method method;
	        		int a=-1;
					try {
				    System.out.println("startformat");
					method = Class.forName("android.os.ServiceManager").getMethod("getService", String.class);//利用反射得到ServiceManager类中的getService方法 
	        		IBinder binder = (IBinder) method.invoke(null, "mount");
	        		IMountService iMountService = IMountService.Stub.asInterface(binder);
	        		iMountService.unmountVolume(sDStateString, true,false);//卸载T卡

	        		SystemClock.sleep(4000);
	        		
	        		a=iMountService.formatVolume(sDStateString);
	        		System.out.println(a);
	        		if(a==0){
	        			iMountService.mountVolume(sDStateString);
	        		}
	        		
					} catch (Exception e) {
						System.out.println("输出异常信息="+e.getMessage());
						e.printStackTrace();
					}

	        	}
	        	
	        	@Override  
	            public void handleMessage(Message msg) {
	        		
	        		//格式化Sdcard卡服务
	        		
	        		formatSdcard();
	        		
	            	/*
	        		//子线程执行体
	            	System.out.println(" handleMessage CurrentThread = " + msg.what);
	            	System.out.println(" handleMessage CurrentThread = " + msg.getTarget());
	            	
	                //打印线程的名称 和ID  
	                System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());
	                System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getId());
	                
	                //textview.setText("hahahahahhahahahah");注意这里是子线程更新UI组件是禁止的,注意HandlerThread
	                //不能用于UI更新
	                Toast.makeText(MainActivity.this, "haha",
	        				Toast.LENGTH_LONG).show();
	        		
	        		*/
	                  
	            }
	        	
	        	
	        	
	        };
		}

	@Override
	public void onClick(View v) {
		
		//点击按钮后来开启线程 ,线程触发指令,想MQ中投递消息
        handler.sendEmptyMessage(1); 
 	
	}

	/*
	private class MyHandlerThread extends HandlerThread implements Callback {  
		  
        public MyHandlerThread(String name) {  
            super(name);  
        }  
  
        @Override  
        public boolean handleMessage(Message msg) {
        	
        	System.out.println(" handleMessage CurrentThread = " + msg.what);
        	System.out.println(" handleMessage CurrentThread = " + msg.getTarget());
        	
            //打印线程的名称 和ID  
            System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getName());
            System.out.println(" handleMessage CurrentThread = " + Thread.currentThread().getId());
            
            return true;  
        }
        
        */
	}	



二.布局文件

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.testhanlerthread.MainActivity$PlaceholderFragment" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/handlerThreadBtn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/textView1"
        android:layout_below="@+id/textView1"
        android:layout_marginTop="99dp"
        android:text="@string/startHandlerThread" />

</RelativeLayout>


三.配置文件

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.testhanlerthread"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />
    <permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS">
    </permission>
    <permission android:name="android.permission.MOUNT_FORMAT_FILESYSTEMS">
    </permission>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.testhanlerthread.MainActivity"
            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>

</manifest>


四.引入的包

由于sd卡的卸载服务,我们采用了AIDL远端服务,因此我们应该导入包含此服务的android.jar的包,这里还利用了反射机制,进行hide服务的获取情况,因此本例子是一个非常典型的综合服务的情况。

4.异步任务类


5.两种线程以及异步任务类的区别


0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:6035次
    • 积分:281
    • 等级:
    • 排名:千里之外
    • 原创:23篇
    • 转载:0篇
    • 译文:0篇
    • 评论:1条
    最新评论