Androidマルチスレッド解析の5:AyncTaskを使って非同期で画像をダウンロードする

6892 ワード

Androidマルチスレッド解析の5:AyncTaskを使って非同期で画像をダウンロードする
羅朝輝http://www.cnblogs.com/kesalin)
CC許可、転載は出所を明記してください.
本シリーズの第一編「Androidマルチスレッド解析の一つ:Thread非同期を使って画像をダウンロードする」では、Threadを使って非同期のミッションを達成する方法を実証しました.Androidは、UIスレッド内で非同期タスクを完了するために、AysncTaskというテンプレートクラスを実現した.AysncTaskを使用して、UIスレッドにプログレスバーを更新させるなど、タスク進捗状態をUIスレッドにフィードバックすることができる.UIスレッドと密接に関連しているからこそ、AysncTaskはUIスレッドで作成し、UIスレッドで起動しなければならない.また、AysncTask設計の目的は、時間がかかる短いタスクのためです.時間がかかるタスクであれば、推奨されていません. AysncTask
「3パラメータ,4ステップ」を簡単に記憶することでAysncTaskを学ぶことができます.すなわち、三つのテンプレートパラメータ<Paraams、Progess、Resoult>を持ち、四つの処理ステップ:onPreExecute、doInBackground、onProgress Update、onPostExecute.
三パラメータ:
Paraamsは、非同期タスクに必要なパラメータタイプであり、つまりdoInBackground(Params)です. メソッドのパラメータタイプPrograessとは、プログレスのパラメータタイプ、すなわちonProgress Updateのことです. メソッドのパラメータタイプResultとは、タスクが完了して戻ってくるパラメータタイプ、すなわち、 onPostExecute(Result result)または onCancelled(Result reult) メソッドのパラメータタイプ.
あるパラメータタイプが意味がない場合や使われていない場合は、voidを転送すればいいです.
四段階:
プロテcted void onProExecute():UIスレッドで実行され、非同期タスクが開始される前に実行され、UIスレッドがいくつかの初期化動作を完了するために、プログレスバーをクリアするなど、いくつかの初期化動作が実行される.protected abstract Result doInBackground:バックグラウンドスレッドで動作します.これは非同期のタスクを完了するところです.抽象的なインターフェースです.サブクラスは実現を提供しなければなりません.protected void onProgress Update:UIスレッドで実行され、非同期タスクの実行中に呼び出しを行うことができます. void publish Progress.values方法通知UIスレッドは OProgress Update方法内で進捗状況を更新する.protected void onPostExecute:UIスレッドで実行され、非同期タスクが完了すると、UIスレッドがタスク完了状態を更新するために実行されます.
AysncTaskは非同期タスクをキャンセルすることをサポートしています.非同期タスクがキャンセルされた後、上記のステップ4は実行されなくなり、代わりに実行されます. OnCancelledは、UIスレッド更新タスクがキャンセルされた後の状態になります.注意:これらの方法はすべてコールバック関数であり、ユーザが手動で呼び出す必要はありません.
以前のAysncTaskは単一のバックグラウンドスレッドに基づいて実現されていたが、Android 3.0からAysncTaskはAndroidベースの合併ライブラリ(java.util.co ncurrent)によって実現されたものであり、本明細書では具体的な実装について議論することはなく、AysncTaskをどのように使用するかを示すものである.
使用例:
前の輪郭が紹介されました.また使います. AysncTaskはとても簡単です.以下の例は「Thread非同期ダウンロード画像を使用する」の例と非常に似ています. AysncTaskは非同期の任務を完成しただけです.
これはAysncTaskを使うものです. ネットワークから画像を非同期的にダウンロードし、ImageViewに表示する簡単な例.ネットワークにアクセスする必要があるので、maifest.xmlにネットワークアクセス権限を追加します.
	<uses-permission android:name="android.permission.INTERNET">
	</uses-permission>
レイアウトファイルは簡単です.Button、ImageView:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dip" >

	<Button
		android:id="@+id/LoadButton"
		android:layout_width="fill_parent"
		android:layout_height="wrap_content"
		android:text="Load">
	</Button>

	<ImageView
		android:id="@+id/ImageVivew" 
		android:layout_width="match_parent" 
		android:layout_height="400dip" 
		android:scaleType="centerInside" 
		android:padding="2dp">
	</ImageView> 
	
</LinearLayout>
次にコードを見ます.
まず定義を見てみます.画像のurl経路、二つのメッセージ値、およびいくつかのコントロール:
    private static final String sImageUrl = "http://fashion.qqread.com/ArtImage/20110225/0083_13.jpg";
    private Button mLoadButton;
    private ImageView mImageView;
次にコントロールの設定を見ます.
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		Log.i("UI thread", " >> onCreate()");
		
		mImageView = (ImageView)this.findViewById(R.id.ImageVivew);
		
		mLoadButton = (Button)this.findViewById(R.id.LoadButton);
		mLoadButton.setOnClickListener(new View.OnClickListener() {
            @Override 
            public void onClick(View v) {
            	LoadImageTask task = new LoadImageTask(v.getContext());
                task.execute(sImageUrl);
            }
        });
	}
LoadImageTask継承 AysncTaskは、このクラスで非同期画像のダウンロードタスクを完了し、それに応じてUI状態を更新する.
	class LoadImageTask extends AsyncTask<String, Integer, Bitmap> 
	{
		private ProgressDialog mProgressBar;
	    
		LoadImageTask(Context context)
		{
			mProgressBar = new ProgressDialog(context);
			mProgressBar.setCancelable(true);
			mProgressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			mProgressBar.setMax(100);
		}
		
		@Override
		protected Bitmap doInBackground(String... params) {
			Log.i("Load thread", " >> doInBackground()");
			
			Bitmap bitmap = null;
			
			try{
				publishProgress(10);
				Thread.sleep(1000);
				
	            InputStream in = new java.net.URL(sImageUrl).openStream();
	            publishProgress(60);
				Thread.sleep(1000);
				
	            bitmap = BitmapFactory.decodeStream(in);
	            in.close();
            } catch (Exception e) {
            	e.printStackTrace();
			}

			publishProgress(100);
			return bitmap;
		}
		
		@Override
		protected void onCancelled() {
            super.onCancelled();
        }
		 
	    @Override
        protected void onPreExecute() {
		
			mProgressBar.setProgress(0);
	    	mProgressBar.setMessage("Image downloading ... %0");
	    	mProgressBar.show();
	    	
	    	Log.i("UI thread", " >> onPreExecute()");
        }
	     
	    @Override
        protected void onPostExecute(Bitmap result) {
	    	Log.i("UI thread", " >> onPostExecute()");
	    	if (result != null) {
		    	mProgressBar.setMessage("Image downloading success!");
	        	mImageView.setImageBitmap(result);
	    	}
	    	else {
		    	mProgressBar.setMessage("Image downloading failure!");
	    	}

            mProgressBar.dismiss(); 
        }
        
	   @Override
		protected void onProgressUpdate(Integer... values) {
		   Log.i("UI thread", " >> onProgressUpdate() %" + values[0]);
		   mProgressBar.setMessage("Image downloading ... %" + values[0]);
		   mProgressBar.setProgress(values[0]);
		}
	};
はい、 LoadImageTaskにおいて、前述の4つのステップは、以下の通りである.
まず任務が始まる前に オンProExecute()方法では、プログレスバーの初期状態(UIスレッド)を設定します.ダウンロードスレッドで実行 doInBackground() を選択します. publish ProgressはUIスレッドの更新進捗状況を通知します.UIスレッドは プログレスUpdate()で進捗を知り、プログレスバー(UIスレッド)を更新する.最後にミッションをダウンロードしました.UIスレッドはワンポイントExecuteにあります. でダウンロードされた画像を知り、UIを更新して画像(UIスレッド)を表示する.