スレッド

AndrroidのUIスレッド(メインスレッド)はSingleton Threadのため、Thread Safeではない

UIスレッドのみはUIコントロールにアクセスできる

UIスレッドを塞がないように下記の方法で解決できる

・HandlerとLooper

MessageQueue、Message

・Activity.runOnUIThread(Runnable)

・View.post(Runnable)或いはView.postDelayed(Runnable, long)

・AsyncTask

引数

1、Params

2、Progress

3、Result

Callback

1、onPreExecute

2、doInBackground

3、onProgressUpdate

4、onPostExecute

非同期処理 HandlerとAsyncTask

import java.io.IOException;

import java.net.HttpURLConnection;

import java.net.MalformedURLException;

import java.net.URL;

import android.app.Activity;

import android.app.ProgressDialog;

import android.graphics.Bitmap;

import android.graphics.BitmapFactory;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.FrameLayout;

import android.widget.ImageView;

import android.widget.ProgressBar;

public class AndroidTestActivity extends Activity implements OnClickListener {

private static final String TAG

= AndroidTestActivity.class.getSimpleName();

private static final String PATH1

= "http://careercrud.appspot.com/images/log_in.png";

private static final String PATH2

= "http://careercrud.appspot.com/images/log_out.png";

private static final int SUCCESS = 1;

private FrameLayout frameLayout = null;

private Bitmap bitmap = null;

private ProgressDialog dialog = null;

// ★方法1 Handlerメンバ変数が繰り返し、実行できる

private Handler handler = new Handler(){

@Override

public void handleMessage(Message msg){

switch(msg.what){

case SUCCESS:

ImageView view

= (ImageView)frameLayout.findViewById(R.id.image);// 書き方1

view.setImageBitmap(bitmap);

dialog.dismiss();

break;

}

}

};

// ★方法2 AsyncTaskメンバ変数が一回のみ、繰り返し、実行できないため、ローカル変数にしよう

// private AsyncTask<String, Integer, Bitmap> asyncTask = new AsyncTask ×

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.main);

Button btn1 = (Button)findViewById(R.id.btn1);

Button btn2 = (Button)findViewById(R.id.btn2);

btn1.setOnClickListener(this);

btn2.setOnClickListener(this);

ProgressBar progress = (ProgressBar)findViewById(R.id.progress);

progress.setVisibility(View.GONE);

frameLayout = (FrameLayout)findViewById(R.id.frameLayout);

}

public void onClick(View v) {

dialog = ProgressDialog.show(this, "", "Wait...", true, true);

switch(v.getId()){

case R.id.btn1:

// 別スレッドを起動

handler.post(new Runnable(){

public void run() {

// ファイルをダウンロード

bitmap = getBitmapByHttp(PATH1);

//newよりMessagePoolから取得した方が効率よい

//Message msg = new Message();

Message msg = handler.obtainMessage(); Better

msg.what = SUCCESS;

//msg.arg1 = SUCCESS;

//msg.arg2 = SUCCESS;

handler.sendMessage(msg);

}

});

break;

case R.id.btn2:

AsyncTask<String, Integer, Bitmap> asyncTask = new AsyncTask<String, Integer, Bitmap>() {

@Override

protected Bitmap doInBackground(String... params) {

return getBitmapByHttp(params[0]);

}

@Override

protected void onPostExecute(Bitmap result) {

ImageView imgView

= (ImageView)frameLayout.getChildAt(0); // 書き方2

imgView.setImageBitmap(result);

dialog.dismiss();

}

};

asyncTask.execute(PATH2);

break;

}

}

private Bitmap getBitmapByHttp(String path) {

HttpURLConnection conn = null;

Bitmap bitmap = null;

try {

URL url = new URL(path);

conn = (HttpURLConnection)url.openConnection();

bitmap = BitmapFactory.decodeStream(conn.getInputStream());

}

catch (MalformedURLException e) {

Log.d(TAG, "Exception", e);

}catch (IOException e) {

Log.d(TAG, "Exception", e);

} finally {

if(conn != null){

conn.disconnect();

}

}

return bitmap;

}

}

★Handler

実はスレッドをstart()させないまま、単にrun()を呼ぶだけで、Message Queueに基づく

特徴:

・コード量が多いが、コストが低い

・通信量が少ない時に利用

利用方法1 boolean sendMessage(Message msg)

手順:

1.UIスレッドの中にHandler(handleMessageメソッドを実装)をnewする

2.子スレッドの中にnew済みのHandler(sendMessageメソッドでメッセージを送る)を呼び出す

サンプルは左側のコードを参照

利用方法2 boolean post(Runnable r)

手順:

1.UIスレッドの中にHandlerをnewする

2.Runnable(runメソッドを実装)をnewする

3.子スレッドの中にnew済みのRunnable(postメソッドで呼ぶ)を呼び出す

サンプルはソーシャルを参照

★AsyncTask

実はスレッドプール

特徴:

コード量が少ないが、コストが高い

通信量が多い時に利用

注意点:

1.Taskは必ずUIスレッドの中にnewする

2.executeは必ずUIスレッドの中に呼ぶ

3.Taskは一回のみ実行される

new AsyncTask<Params, Progress, Result>().execute(Params... params)

onPreExecute()

doInBackground(Params…)

onProgressUpdate(Progress…)

onPostExecute(Result)

o