●程式說明--多重執行緒補充

=>run倒數計時

(一)conuntDownTimer=>非多重執行緒,是在主執行緒做
public class MainActivity extends AppCompatActivity {
    TextView mTextField;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextField=(TextView)findViewById(R.id.mTextField);
        //每秒鐘執行一次,總共執行30CountDownTimer,都是在主執行緒執行
        new CountDownTimer(300001000) {
           //倒數時要run的程式
            public void onTick(long millisUntilFinished) {
                mTextField.setText("seconds remaining: " + millisUntilFinished / 1000);
            }
            //結束後要run的程式
            public void onFinish() {
                mTextField.setText("done!");
            }
        }.start();
    }
}
**說明:
1.CountDownTimer (long millisInFuture, long countDownInterval)
=>Parameters
millisInFuture long: The number of millis in the future from the call to start() until the countdown is done and onFinish() is called.
countDownInterval long: The interval along the way to receive onTick(long) callbacks.
 
=>問題:因為onTick和onFinsish都是在主執行緒上跑,如果在這兩個method中跑很花時間的程式,還是會讓程式卡住ex,如果再onTick中加入,就會跑一下跳過兩秒,29=>26=>23....程式被卡住了
try {
    Thread.sleep(2000);
catch (InterruptedException e) {
    e.printStackTrace();
}
 
(二)使用runOnUi
public void runonui(View view) {
        new Thread(){
            int 5;
            @Override
            public void run() {
                super.run();
                do {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            tv2.setText(String.valueOf(i));
                        }
                    });
                    i--;
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } while (i>=0);
            }
        }.start();
    }
}
 
(三)使用Handler
public class MainActivity extends AppCompatActivity {
    TextView tv3;
    Handler handler;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv3=(TextView)findViewById(R.id.tv3);
handler=new Handler();
}
public void onhandler(View view) {
new Thread(){
int i = 5;
@Override
public void run() {
     super.run();
do {
     handler.post(new Runnable() {
     @Override
     public void run() {
          tv3.setText(String.valueOf(i));
     }
     });
i--;
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
} while (i>0);
}
}.start();
}
}
**說明:
1.handler是android才有,java沒有的class
2.handler的method會在宣告handler的執行緒上run
3.這裡在主執行緒上宣告handler物件,在其他執行緒上用handler.post(~),就會在主執行緒上執行post中的內容
4.實際上run的方法則是和runOnUi一樣,但使用上比較彈性,不限定只能在主執行緒上跑
 
(四)AsynTask=>處理執行緒和ui的機制,有六大function
=>因為是抽象類別而且有抽象方法,所以要繼承和override
=>繼承的時候,可以看到有三個泛型參數
1.執行 AsynTask要傳甚麼類型的資料(傳入的型別)
2.回報進度的型別
3.結果的型別(ex:如果是抓網路文字資料就是字串,如果是抓網路圖片就是bitmap)
 
//建立一個內部類別繼承AsynTask
class MyAsynTask extends AsyncTask<Integer,Integer,String>{
    //因為要使用MainActivity的tv4但是不要設定static,就利用建構式把tv4傳進來
    TextView tv;
    public MyAsynTask(TextView tv){
        this.tv=tv;
    }
 
 
    //override doInBackground方法=>在背景執行
    //這邊的參數類型會和繼承時決定的傳入型別一樣,...是參數列表與陣列類似,可以一個或多個參數
    //ex:abc(int [ ] x):void; 或 abc(int... x):void;
    @Override
    protected String doInBackground(Integer... integers) {
        int n = integers[0];
        int i;
        for(i=n;i>=0;i--)
        {
            Log.d("TASK", "i:" + i);
            //publishProgress(Progress... values): to publish updates on the UI thread while the background computation is still running
            //參數:values Progress: The progress values to update the UI with.
            publishProgress(i);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //Returns true if this task was cancelled before it completed normally
            if (this.isCancelled() == true)
            {
                break;
            }
        }
        return "OK";
    }
 
 
    @Override
    //在執行之後
    //會在doInBackground執行完之後才執行,而且是在主執行緒執行,並且doInBackground return的內容會丟到這邊的參數帶入
    //所以看log這邊會顯示ok
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
        Log.d("TASK", s);
    }
 
 
    @Override
    //進度更新,也是在主執行緒跑
    //這邊的Integer...values是MyAsynTask<>第二個帶入的參數類型,由publishProgerss()傳值過來
    //必須在 doInBackground加上publishProgress();
    protected void onProgressUpdate(Integer... values) {
        super.onProgressUpdate(values);
        tv.setText(String.valueOf(values[0]));
    }
 
 
    @Override //當呼叫cancel method,會run onCancelled()
    /*onCancelled
    Applications should preferably override onCancelled(Object). This method is invoked by the default implementation of onCancelled(Object).
    Runs on the UI thread after cancel(boolean) is invoked and doInBackground(Object[]) has finished.*/
    protected void onCancelled() {
        super.onCancelled();
 
 
    }
}

 

 

●程式參考(GitHub):多重執行續的補充說明(CountDownTimer、Handler、runOnUiThread、AsynTask)

arrow
arrow
    創作者介紹
    創作者 muchone 的頭像
    muchone

    簡單。生活。享受

    muchone 發表在 痞客邦 留言(0) 人氣()