----------------------------------------------------------------------
1. Program 與 Process 觀念:
----------------------------------------------------------------------
Program:
一群程式碼的集合,用以解決特定的問題。以物件導向的觀念來類比,相當於Class。
Process:
由Program所產生的執行個體,一個Program可以同時執行多次,產生多個Process。以物件導向的觀念來類比,相當於Object。每一個Process又由以下兩個東西組成
1. 一個Memory Space。相當於Object的variable,不同Process的Memory Space也不同,彼此看不到對方的Memory Space。
2. 一個以上的Thread。Thread代表從某個起始點開始(例如main),到目前為止所有函數的呼叫路徑,以及這些呼叫路徑上所用到的區域變數。當然程式的執行狀態,除了紀錄在主記憶體外,CPU內部的暫存器(如Program Counter, Stack Pointer, Program Status Word等)也需要一起紀錄。所以Thread又由下面兩項組成
a. Stack:紀錄函數呼叫路徑,以及這些函數所用到的區域變數
b. 目前CPU的狀態
參考資料:
----------------------------------------------------------------------
2. Thread的使用
----------------------------------------------------------------------
- Thread 線程:
指運行中的程序的調度單位。一個線程指的是進程(Processes)中一個單一順序的控制流。它是系統獨立調度和分派的基本單位。同一進程中的多個線程將共享該進程中的全部系統資源,比如文件描述符和信號處理等等。 一個進程可以有很多線程,每個線程并行執行不同的任務。.所以意思就是當主程式在進行時,同時又需要去執行別的任務,就可以另起一個Thread(線程),將要執行的內容在背後運作,等到執行完成後,再把結果秀出來
- Android Thread:
1. Android於Thread有一個重要的限制「Android為了考量安全性和執行效能,不允許副執行緒直接更改主畫面的資料」,也就是說在我們另起的Thread都沒辦法做出如:將畫面變色與改變文字內容等畫面上的行為,而解決方法就是利用"Handler"來做溝通的橋樑。
2. MainThread(UI Thread)和Worker Thread:
a. 所有与UI有关的代码写在MainThread当中。
b. 主线程不能阻塞,主线程一般不进行耗时较长的操作,比如联网下载,读取大文件等。
- Android Activity 間传递数据的方法:
Intent对象的基本概念:
1. Intent是Android应用程序组件之一
2. Intent对象在Android系统中表示一种意图
3. Intent当中最重要的内容是action与data
使用Intent在Activity之间传递数据的方法:
1. 在Activity之间可以通过Intent对象传递数据
2. 使用putExtra()系列方法向Intent对象当中存储数据
3. 使用getXXXExtra()系列方法从Intent对象当中取出数据
- 整個流程是:.
1. 主執行緒開始執行。.
2. 需要Thread(副執行緒)運行比較久的程序,開始執行Thread。.
3. Thread於背景執行(通常附帶時間控管,如Thread.sleep(1000);).
4. Thread完成,傳送訊息告知Handler。.
5. 執行Handler內的邏輯程式,改變畫面內容。
- 如何產生Thread
1. Class Thread有兩個Constructor:
(1) Thread()
(2) Thread(Runnable)
2. Runnable是一個interface,定義於java.lang內,其宣告為
public interface Runnable {
public void run();
}
3. 使用Thread()產生的Thread,其進入點為Thread裡的run();
4. 使用Thread(Runnable)產生的Thread,其進入點為Runnable物件裡的run()。
5. 當run()結束時,這個Thread也就結束了 。
6. 啟動 thread 時,使用 start() 方法:Thread.start();
7. 清除 thread 時,使thread 為 null: Thread = null;
(1)Thread thread = new Thread(){
@Override
public void run() {
} }
| (2) Thread thread = new Thread();
Runnable1 r1 = new Runnable1(“test”);
thread(r1).start();
class Runnable1 implements Runnable {
/* 附加執行的副程式 */
private String name;
public Runable1 (String name) {
this.name = name;
}
/* Runnable 主體 */
public void run(){
}
};
|
•Thread的優先權
–優先權高的Thread其佔有CPU的機會比較高,但優先權低的也都會有機會執行到。
–Thread.setPriority(int):設定Thread的優先權,數字越大優先權越高。
–public static final int MAX_PRIORITY 10
public static final int MIN_PRIORITY 1
public static final int NORM_PRIORITY 5
•其他有關Thread執行的方法有:
–yield():先讓給別的Thread執行
–sleep(int time):休息time mini second(1/1000秒)
–join():呼叫ThreadA.join()的執行緒會等到ThreadA結束後,才能繼續執行
•Critical Section(關鍵時刻)的保護措施
–如果設計者沒有提供保護機制的話,Thread取得和失去CPU控制權的時機是由作業系統來決定。
–Java的解決辦法是,JVM會在每個物件上擺一把鎖(lock),然後程式設計者可以宣告執行某一段程式時,必須拿到某物件的鎖才行,這個鎖同時間最多只有一個執行緒可以擁有它。
–Ex: 1. 使用string 或 int 等變數 flag 及 if else 判斷式來進行保護。
2. 使用 try catch 排除例外狀況
- Handler、Looper和MessageQueue的基本原理?
Handler把消息对象添加到MessageQueue中,Looper负责从MessageQueue的头部不断取出消息对象,取出一个消息对象之后交给Handler处理。
Message msg = handler.obtainMessage();//获取Message对象
msg.what = 2;//给Message属性赋值,msg.obj = s; // 6. 把s赋值给obj
handler.sendMessage(msg);//把消息对象放到消息队列当中去
//1. Looper将会从消息队列当中将消息对象取出,
//2. Looper将会找到与消息对象对应的Handler对象(每一个消息对象都有一个对应的Handler对象)。
//3. Looper将会调用消息对象的handleMessage(Message msg)方法,用于处理该消息对象
EX:
public class MainActivity enxtends Activity {
private Textview textview;
private Button button;
private Handler handler; //3. 定义一个变量
@Override
protected void conCreate(Bundle savedInstanceState) {
super.onCreate(savedINstanceState);
setContentView(R.layout.activity_main);
textView = (TextView)findViewById(R.id.textViewId);
button = (Button)findViewById(R.id.buttonId);
handler = new Myhandler(); //4.使用Myhandler类生成对象
button.setOnClickListener(new ButtonListener());//绑定监听器
}
class MyHandler extends Handler {
//1.首先定义一个handler的实现类,继承Handler
@Override
public void handleMessage(Message msg) {
//2. 然后实现handleMessage方法
System.out.println("handleMessage--->" + Thread.currentThread().getName()); // 测试说明:打印当前线程的名字
String s= (String)msg.obj; // 8. 在主线程中将数值取出
textView.setText(s); //在主线程中操作UI
}
}
class ButtonListener implements OnClickListener {
@Override
public void onClick(View v) {
Thread t = new NetWorkThread();
t.start();
}
}
class NetworkThread extends Thread {
//本线程为Worker Thread
//@Override
public void run(){
System.out.println("network--->" + Thread.currentThread().getName()); // 测试说明:打印当前线程的名字
//模拟访问网络,所以当线程运行时,首先休眠2秒
try {
Thread.sleep(2 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//变量s的值,模拟从网络中获取的数据
String s = "网络中的数据";
//textView.setText(s);//这样的操作是错误的,安卓系统中UI操作原则上只能在主线程中进行
Message msg = handler.obtainMessage(); // 5.生成Message对象
//sendMessage方法无论在主线程中发送还是在Worker Thread中发送都可以,这里在WorkerThread当中发送,然后在主线程将消息取出。
msg.obj = s; // 6. 把s赋值给obj
handler.sendMessage(msg); // 7. 调用sendMessage方法发送消息
}
}
}
參考資料:
----------------------------------------------------------------------
3. 安全中止一個Thread
----------------------------------------------------------------------
class MyThread implements Runnable{
public void run() {
// TODO Auto-generated method stub
// 定义自己的变量
while(!Thread.currentThread().isInterrupted()){
try {
doSomeThingNeed();//需要更新的操作
//休眠控制最大帧率为每秒3绘制30次
Thread.sleep(30);
} catch (Exception e) {
// TODO: handle exception
Log.v(tag2, "DrawSurfaceView:绘制失败...");
Thread.currentThread().interrupt();
}
}
}
參考資料:
----------------------------------------------------------------------
4. Thread傳Message到Handler
----------------------------------------------------------------------
•在Thread中並沒有辦法改變畫面上的任何UI,所以會使用Handler來完成UI更新的目的。
•在 Android 中,Activity 可透過 Handler 傳遞Message 去切換不同的 UI 介面 (setContentView( View、SurfaceView、R.Layout.xml_file ))
•但在計算中並不是都會正確的完成,所以在Handler中也必須判斷Thread的執行狀況來做出不同的反應,那麼就必須依靠Message來完成兩者間的資訊傳遞
1. 建立一個Thread,並傳遞指定相關資訊到Message中,利用handler.sendMessage傳遞出去。
Thread thread = new Thread(){ @Override public void run() { Message message; String obj = "OK"; message = handler.obtainMessage(1,obj); handler.sendMessage(message); }
}
thread.start();
thread = null;
| 2. 於handler中依照傳遞的訊息做出相對應的反應
private Handler DOFindAttributehandler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); String MsgString = (String)msg.obj; if (MsgString.equals("OK")) { ...... } } };
|
P.S: Override 為覆寫繼承之父類別中的方法,若覆寫完後仍須使用原方法時,即用super (指向繼承之父類別)
參考資料:
在 main thread 執行時,會產生 ANR (Application is Not Responding)的對話框,並且終止程式。
text = (TextView)findViewById(R.id.textView);
int i =0;
while(true){ // 無窮迴圈造成 ANR。
i++;
text.setText(Integer.toString(i));
}
new Thread(new Runnable(){
@Override
public void run() {
// TODO Auto-generated method stub
while(true){ // 保護機制
try{
Message msg = new Message();
msg.what = 1;
mHandler.sendMessage(msg);
Thread.sleep(500); // 休息500ms
}
catch(Exception e){
e.printStackTrace();
}
}
}
}).start();
| text = (TextView)findViewById(R.id.textView);
mHandler = new Handler(){
int i = 0;
@Override
public void handleMessage(Message msg) {
switch(msg.what){
case 1:
i++;
text.setText(Integer.toString(i));
break;
}
super.handleMessage(msg);
}
};
|
參考資料: