編輯:關於Android編程
今天面試的時候,面試官和我說起同步和異步,因為說起同步我就是想到線程同步,然後共享臨界資源啊死鎖啊什麼的,所以一直在說這個,線程異步倒是從來沒聽過。剛才看了場球想起這件事查了一下,不知道他說的異步是不是期待我回答用Handler來刷新主線程的意思,我平常管這個叫異步任務- -昨天一面的時候,面試官問的就是怎樣刷新UI線程,然後我就說用AsyncTask。好了,既然如此不管了,因為之前就想把以前寫的那篇AsyncTask重寫了。也算是讓焦急的等待時間過快點吧。
Android從2.3(還是3.0…?)開始就不允許在主線程裡面執行一些比較耗時的任務,通常我們需要用一個異步任務的機制解決在子線程裡面刷新UI的問題。
簡單翻譯一下API上幾個重要的類:(我應該問面試官有沒相關的類可以提醒一下的)
Message:
定義一個可以攜帶一些字段或對象數據的消息對象,官方推薦實例化方式是:Message.obtain() MessageQueue:
存放消息的隊列 Handler:
當你創建一個新的Handler時,他就和當前線程創建的MessageQueue綁定了。主要有兩個作用,一個是將消息入隊,另外一個是處理消息。 Looper:
運行線程message queue的一個類,線程默認是不帶message queue的,可以通過prepare()
和loop()
來創建。而主線程是自帶message queue的。
盜流程示意圖一張:
目前我所知道的實現異步任務的方法有三個:
使用Handler + Message
來實現 使用AsyncTask
類 調用runOnUiThread()
方法
下面以代碼注釋形式來講解一下三種方法的使用:
public class MainActivity extends ActionBarActivity {
private TextView textView;
// 匿名內部類實例化一個Handler對象
private Handler handler = new Handler() {
// 重寫handleMessage方法,通過異步消息機制實現子線程刷新UI
public void handleMessage(Message msg) {
textView.setText("you got " + msg.what + " through handler");
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
new TestThread().start();
}
private class TestThread extends Thread {
private int i = 1;
public void run() {
while (true) {
/* 這裡需要注意一下,我們可以Message message = Message.obtain()獲得Message對象,然後用Handler調用sendMessage()方法,更多詳細的方法可以參考API*/
handler.sendEmptyMessage(i++);
if (i > 100)
break;
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
這裡直接把之前那篇文章的代碼貼過來,因為後面應該會刪掉那篇文章。
public class MainActivity extends ActionBarActivity {
Private TextView textView;
Private Button button;
Private MyAsyncTask asyncTask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
button = (Button) findViewById(R.id.button);
asyncTask = new MyAsyncTask();
// 點擊button進行異步任務
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
asyncTask.execute("Leelit"); // 這個參數就是傳入參數,常用於URL網絡下載,可以為空。
}
});
}
/* 泛型類AsyncTask有三個參數:Params,傳入參數;Progress,進度;Result,返回結果。也可以使用Void表示該參數為空。*/
private class MyAsyncTask extends AsyncTask {
@Override
protected String doInBackground(String... string) {
// TODO Auto-generated method stub
String conutString = string[0]; // 字符串可變參數
int z = 0;
// 進行5億次計算,模擬一個耗時任務
for (int i = 0; i < 1000000; i++) {
for (int j = 0; j < 500; j++) {
z++;
}
}
conutString += " has executed ++ computation for " + z + " times";
Log.e("ProcessInfo", "the task is done");
return conutString; // 將計算結果返回,傳給onPostExecute()
}
@Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
textView.setText(result); // 刷新UI
}
}
}
如果需要顯示任務進度的話,可以重寫另外一個方法:
// 可變參數的類型就是泛型的第二個參數,因為我這裡不需要所以就是Void
@Override
protected void onProgressUpdate(Void... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
}
並在doInBackground()
方法調用publishProgress()
直接在子線程裡面調用這個方法就可以實現對主線程的操作,是最簡單的操作
public class MainActivity extends ActionBarActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = (TextView) findViewById(R.id.textview);
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
final String result = "After a long-time execution";
// 直接在子線程調用即可
runOnUiThread(new Runnable() {
public void run() {
textView.setText(result);
}
});
}
}).start();
}
}
看一下這個這麼簡單的方法的源碼
public final void runOnUiThread(Runnable action) {
if (Thread.currentThread() != mUiThread) {
mHandler.post(action);
} else {
action.run();
}
}
沒錯,可以看到就是通過封裝Handler來實現的,其實AsyncTask也是如此,不過AsyncTask的機制復雜一點。
小結:異步任務可用Handler及其封裝的類或方法來實現
在Android中通過ListView顯示SD卡中的文件列表一共有兩種方法,一是:通過繼承ListActivity顯示;二是:利用BaseAdapter顯示。BaseAd
本人新手,由於要做郵件發送驗證碼,所以找到和搜集到這些,本人親測完全可以用這是163郵箱的 因為不是企業郵箱填寫的賬號是163的賬號,但是密碼是授
很多時候我們開發的軟件需要向用戶提供軟件參數設置功能,例如我們常用的QQ,用戶可以設置是否允許陌生人添加自己為好友。對於軟件配置參數的保存,如果是window軟件通常我們
本文實例講述了Android實現Service獲取當前位置(GPS+基站)的方法。分享給大家供大家參考。具體如下:需求詳情:1)、Service中每隔1秒執行一次定位操作