Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 中級開發 >> Android線程的交互,以及使用方法(2)

Android線程的交互,以及使用方法(2)

編輯:中級開發

下面說說我們上邊的那個按鈕怎麼設置那種圖片變換的效果。其實很簡單的,因為我們都知道按鈕有 三種狀態 分別是 當我們的應用程序啟動的時候 有一種狀態默認狀態。 還有就是當我們按下按鈕的時候一種狀態, 最後一種狀態就是 當我們松開這個按鈕的時候也是一種狀態。所有一共有三種狀態。 我們要實現這種效果無非就是 當不同狀態的時候去引用不同的圖片資源。 來實現這種效果。 
這裡我找個一個文檔來說明這種配置文件的一些屬性 以及用法。E文的,小的英文灰常之差勁啊。看著太太給力了。基本不懂。 
http://idunnolol.com/android/drawables.Html#selector 
至於到底該怎麼配置和設置大家看例子就是了 這裡就不過多解釋了。 
   
   累了嗎?可以去喝喝茶。回來我們繼續。下面我們 來看看人人皆知的AsyncTasks類 Async就是異步的意思,然後Task是任務的意思。翻譯過來就是 異步任務了。首先我要告訴你它是用來搗鼓線程的。 這是你必須要一定要產生一個疑問就是 這個類的處理方式和我們上邊寫的那種 用 Hadler Looper MessageQueue 處理的方式有什麼不同??? 好了這個類我們是必須會。必須會用。必須地。

       其實平常一般都是使用AsyncTask的,而並非Thread和Handler去更新UI,這裡說下它們到底有什麼區別,我們平時應該使用哪種解決方案。從Android 1.5開始系統將AsyncTask引入到android.os包中,過去在很早1.1和1.0 SDK時其實官方將其命名為UserTask,其內部是JDK 1.5開始新增的concurrent庫,做過J2EE的網友可能明白並發庫效率和強大性,比Java原始的Thread更靈活和強大,但對於輕量級的使用更為占用系統資源。Thread是Java早期為實現多線程而設計的,比較簡單不支持concurrent中很多特性在同步和線程池類中需要自己去實現很多的東西,對於分布式應用來說更需要自己寫調度代碼,而為了android UI的刷新Google引入了Handler和Looper機制,它們均基於消息實現,有時可能消息隊列阻塞或其他原因無法准確的使用。

   推薦大家使用AsyncTask代替Thread+Handler的方式,不僅調用上更為簡單,經過實測更可靠一些,Google在Browser中大量使用了異步任務作為處理耗時的I/O操作,比如下載文件、讀寫數據庫等等,它們在本質上都離不開消息,但是AsyncTask相比Thread加Handler更為可靠,更易於維護,但AsyncTask缺點也是有的比如一旦線程開啟即dobackground方法執行後無法給線程發送消息,僅能通過預先設置好的標記來控制邏輯,當然可以通過線程的掛起等待標志位的改變來通訊,對於某些應用Thread和Handler以及Looper可能更靈活。 
     那麼先讓我們看看要使用AsyncTask 類首先要做哪些工作? 
      1)  子類化AsyncTask 
      2)  實現AsyncTask中定義的下面一個或幾個方法 
         onPreExecute() 開始執行前的准備工作; 
         doInBackground(Params...) 開始執行後台處理,可以調用publishProgress方法來更新實時的任務進度; 
         onProgressUpdate(Progress...)  在publishProgress方法被調用後,UI thread將調用這個方法從而在界面上展示任務的進展情況,例如通過一個進度條進行展示。 
         onPostExecute(Result) 執行完成後的操作,傳送結果給UI 線程。

         這4個方法都不能手動調用。而且除了doInBackground(Params...)方法,其余3個方法都是被UI線程所調用的,所以要求: 
        1) AsyncTask的實例必須在UI thread中創建; 
        2) AsyncTask.execute方法必須在UI thread中調用; 
        
    同時要注意:該task只能被執行一次,否則多次調用時將會出現異常。而且是不能手動停止的,這一點要注意,看是否符合你的需求!

    在使用過程中,發現AsyncTask的構造函數的參數設置需要看明白:AsyncTask<Params, Progress, Result> 
    Params對應doInBackground(Params...)的參數類型。而new AsyncTask().execute(Params... params),就是傳進來的Params數據,你可以execute(data)來傳送一個數據,或者execute(data1, data2, data3)這樣多個數據。 
    Progress對應onProgressUpdate(Progress...)的參數類型; 
    Result對應onPostExecute(Result)的參數類型。 
    當以上的參數類型都不需要指明某個時,則使用Void,注意不是void。

     說到這裡就得多說幾句 你看AsyncTask 你就會發現這個類是個泛型類 這個類是這樣定義的。

Java代碼 
1.public abstract class AsyncTask<Params, Progress, Result> {}  
public abstract class AsyncTask<Params, Progress, Result> {}
在把execute方法的源碼 貼上來供大家參考 。

Java代碼 
1.public final AsyncTask<Params, Progress, Result> execute(Params... params) {   
2.       if (mStatus != Status.PENDING) {   
3.           switch (mStatus) {   
4.               case RUNNING:   
5.                   throw new IllegalStateException("Cannot execute task:"  
6.                           + " the task is already running.");   
7.               case FINISHED:   
8.                   throw new IllegalStateException("Cannot execute task:"  
9.                           + " the task has already been executed "  
10.                           + "(a task can be executed only once)");   
11.           }   
12.       }   
13.  
14.       mStatus = Status.RUNNING;   
15.  
16.       onPreExecute();   
17.  
18.       mWorker.mParams = params;   
19.       sExecutor.execute(mFuture);   
20.  
21.       return this;   
22.   }  
 public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }

        mStatus = Status.RUNNING;

        onPreExecute();

        mWorker.mParams = params;
        sExecutor.execute(mFuture);

        return this;
    }

      這個類判斷哪裡我也不知道它在做什麼沒有繼續往下深入的研究 內力不足。 顯然這個類返回一個AsyncTask實例。 這裡我要提醒大家的的是 onPreExecute();方法  就是告知大家這個前置方法是什麼時候執行的 當執行這個方法的時候 AsyncTask的工作流程就開始了。這裡我沒有用到這個方法就沒有重寫了。但是大家一定要知道有這麼一個方法 ,它可以用來做一些准備和初始化的工作。剛才說到它的工作流程其實就是 這幾個方法的執行順序我就以圖片的形式告知大家。 讓大家明白它們相互之間的執行順序,這裡一定一定 要搞清楚。又得點擊大圖查看圖片了。

 

     好了我們來看例子 我們這個例子 與上一個例子實現的效果是一樣的所以這裡就不貼運行效果了。其實 是稍微有些不同的 有2點不同 上邊那個例子 我們的第一個按鈕 第一個按鈕就是最上邊的那個按鈕 剛開始是沒有顯示TextView 我們點擊第一個按鈕就會顯示TextView並且會開啟一個線程來執行 當我們再點擊的時候 TextView沒有值了 但是我們 這次點擊並不會另外開啟一個線程。 而我們這個例子會。第一個例子(線程交互) 就是顯示TextView值的時候就會開啟一個線程。當我們把TextVIEw的值 置空的時候不會開啟另外一個線程來執行。 
第二點區別就是 我們這個例子 點擊停止按鈕之後 我們的音樂名也消失。其實也是把TextVIEw顯示的值 置空了。 下面我們就來看看這個例子 因為布局都是一樣的 我在這裡就只貼出了2個類。 大家可以下載源碼進行測試。 
示例名稱 :線程交互AsyncTask版 
  MusicServIE類 和 上一個例子一樣的

Java代碼 
1.package xiaohang.zhimeng;   
2.  
3.import android.app.Service;   
4.import android.content.Intent;   
5.import android.media.MediaPlayer;   
6.import android.os.IBinder;   
7.  
8.public class MusicService extends Service{   
9.       
10.    //MediaPlayer對象   
11.    private MediaPlayer player;   
12.       
13.    @Override  
14.    public IBinder onBind(Intent intent) {   
15.        // TODO Auto-generated method stub   
16.        return null;   
17.    }   
18.       
19.    public void onStart(Intent intent, int startId){   
20.        super.onStart(intent, startId);   
21.        //這裡可以理解為裝載音樂文件   
22.        player = MediaPlayer.create(this, R.raw.test);   
23.        //開始播放   
24.        player.start();   
25.    }   
26.       
27.    public void onDestroy(){   
28.        super.onDestroy();   
29.        //停止音樂-停止Service   
30.        player.stop();   
31.    }   
32.}  
package xiaohang.zhimeng;

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;

public class MusicService extends Service{
 
 //MediaPlayer對象
 private MediaPlayer player;
 
 @Override
 public IBinder onBind(Intent intent) {
  // TODO Auto-generated method stub
  return null;
 }
 
 public void onStart(Intent intent, int startId){
  super.onStart(intent, startId);
  //這裡可以理解為裝載音樂文件
  player = MediaPlayer.create(this, R.raw.test);
  //開始播放
  player.start();
 }
 
 public void onDestroy(){
  super.onDestroy();
  //停止音樂-停止Service
  player.stop();
 }
}


Activity02類

Java代碼 
1.package xiaohang.zhimeng;   
2.  
3.  
4.import android.app.Activity;   
5.import android.content.Intent;   
6.import android.os.AsyncTask;   
7.import android.os.Bundle;   
8.import android.view.VIEw;   
9.import android.view.VIEw.OnClickListener;   
10.import android.widget.Button;   
11.import android.widget.TextVIEw;   
12.  
13.public class Activity02 extends Activity {   
14.    public static  String ARGS1;   
15.    private Button myButton;   
16.    private Button myButton01;   
17.    private Button myButton02;   
18.    private TextView myTextView, textVIEw;   
19.  
20.    @Override  
21.    protected void onCreate(Bundle savedInstanceState) {   
22.        super.onCreate(savedInstanceState);   
23.        setContentVIEw(R.layout.main);   
24.           
25.        myTextView = (TextView) findViewById(R.id.myTextVIEw);   
26.        textView = (TextView) findViewById(R.id.textvIEw2);   
27.  
28.        myButton01 = (Button) findVIEwById(R.id.myButton01);   
29.        myButton02 = (Button) findVIEwById(R.id.myButton02);   
30.        myButton = (Button) findVIEwById(R.id.myButton);   
31.        myButton.setOnClickListener(new MyButtonListener());   
32.        myButton02.setOnClickListener(new MyButton02Listener());   
33.        myButton01.setOnClickListener(new Button.OnClickListener() {   
34.            @Override  
35.            public void onClick(VIEw v) {   
36.                String arg2 = Activity02.ARGS1 = "2";   
37.                new task().execute(arg2);   
38.            }   
39.        });   
40.    }   
41.  
42.    // myButton02按鈕的監聽器   
43.    class MyButton02Listener implements OnClickListener {   
44.        @Override  
45.        public void onClick(VIEw v) {   
46.                String arg3 = Activity02.ARGS1 = "3";   
47.                new task().execute(arg3);   
48.        }   
49.    }   
50.    //此類繼承AsyncTask   
51.    private class task extends AsyncTask<String,String, String>{   
52.        //開啟另外一個線程執行任務   
53.        @Override  
54.        protected String doInBackground(String...params) {   
55.            System.out.println("the thread ID is " + Thread.currentThread().getId());   
56.            System.out.println("the thread NAME is " + Thread.currentThread().getName());   
57.            String test = params[0];   
58.            System.out.println("test value is " + test);   
59.            if (params[0] == "1") {   
60.                String arg1 = params[0];   
61.                return arg1;   
62.            }else if(params[0] == "2"){   
63.                //開啟音樂服務   
64.                startService(new Intent(   
65.                "xiaohang.zhimeng.android.MUSIC"));   
66.                //獲取參數值   
67.                String arg2 = params[0];   
68.                return arg2;   
69.            }else if (params[0] == "3") {   
70.                //停止音樂服務   
71.                stopService(new Intent("xiaohang.zhimeng.android.MUSIC"));   
72.                //獲取參數值   
73.                String arg3 = params[0];   
74.                return arg3;   
75.            }else {   
76.                System.out.println("param post error---->");                
77.            }   
78.            return null;   
79.        }   
80.           
81.        //執行完成後傳送結果給UI線程 此方法最後執行   
82.        protected void onPostExecute(String result) {   
83.            CharSequence test_View = myTextVIEw.getText();   
84.            String str = test_VIEw.toString();   
85.            // 當不等於空的時候   
86.            if (!(str.trim().equals(""))) {   
87.                String str1 = "";   
88.                CharSequence charsq = str1;   
89.                myTextVIEw.setText(charsq);   
90.            } else {   
91.                if (result == "1") {   
92.                    //將 myTextVIEw 賦值成 "android小子"   
93.                    String string = "android小子";   
94.                    myTextVIEw.setText(string);   
95.                }else if(result == "2"){//result等於2說明是myButton01那個按鈕也就是開啟音樂服務的那個開始按鈕   
96.                    //獲取資源文件裡邊的音樂名稱   
97.                    String tmusicName = getResources().getString(R.raw.test);   
98.                    int b = tmusicName.lastIndexOf("/");   
99.                    int e = tmusicName.lastIndexOf(".");   
100.                    //截取歌曲名稱   
101.                    String music_Name = tmusicName.substring(b+1, e);   
102.                    System.out.println("music name is " + music_Name);   
103.                    // 在textVIEw上顯示歌曲名稱   
104.                    textVIEw.setText(music_Name);   
105.                }else if(result == "3"){   
106.                    String str_none = "";   
107.                    CharSequence csq = str_none;   
108.                    textVIEw.setText(csq);   
109.                }else {   
110.                    System.out.println("param post error");   
111.                }   
112.            }   
113.        }   
114.    }

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.Net/xqhrs232/archive/2010/12/24/6095684.ASPx

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved