どのように私は私のイメージのダウンローダは、Android上の別のスレッドに移動しますか?
-
24-09-2019 - |
質問
私は私のAndroidデバイス上で実行されている次のコードを持っています。それは素晴らしい作品と素晴らしく、私のリスト項目を表示します。また、それはArrayAdapterで必要だときにのみ、データをダウンロードし、実際に賢いです。しかし、サムネイルのダウンロードが発生している一方で、リスト全体が失速し、それが完成し、ダウンロードになるまで、あなたはスクロールすることはできません。それはまだスクロール喜んで、多分、ダウンロード画像のプレースホルダーを表示し、ダウンロードを完了した後、表示されますので、これをスレッドのいずれかの方法はありますか?
私はちょうどそのUIは別に実行してそれ自身のスレッドに私downloadImageクラスを配置する必要があると思います。しかし、私のコードにこれを追加する方法謎です!
これですべてのヘルプは本当にいただければ幸いです。
private class CatalogAdapter extends ArrayAdapter<SingleQueueResult> {
private ArrayList<SingleQueueResult> items;
//Must research what this actually does!
public CatalogAdapter(Context context, int textViewResourceId, ArrayList<SingleQueueResult> items) {
super(context, textViewResourceId, items);
this.items = items;
}
/** This overrides the getview of the ArrayAdapter. It should send back our new custom rows for the list */
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.mylists_rows, null);
}
final SingleQueueResult result = items.get(position);
// Sets the text inside the rows as they are scrolled by!
if (result != null) {
TextView title = (TextView)v.findViewById(R.id.mylist_title);
TextView format = (TextView)v.findViewById(R.id.mylist_format);
title.setText(result.getTitle());
format.setText(result.getThumbnail());
// Download Images
ImageView myImageView = (ImageView)v.findViewById(R.id.mylist_thumbnail);
downloadImage(result.getThumbnail(), myImageView);
}
return v;
}
}
// This should run in a seperate thread
public void downloadImage(String imageUrl, ImageView myImageView) {
try {
url = new URL(imageUrl);
URLConnection conn = url.openConnection();
conn.connect();
InputStream is = conn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(is);
Bitmap bm = BitmapFactory.decodeStream(bis);
bis.close();
is.close();
myImageView.setImageBitmap(bm);
} catch (IOException e) {
/* Reset to Default image on any error. */
//this.myImageView.setImageDrawable(getResources().getDrawable(R.drawable.default));
}
}
解決
ここで私は自分のアプリケーションで使用しているものの簡易版だ:
// this lives in Application subclass and is reused
public static final ExecutorService EXECUTOR = Executors.newSingleThreadExecutor();
// the method itself
public void attachImage(final String fileUrl, final ImageView view) {
EXECUTOR.execute(new Runnable() {
@Override
public void run() {
final Drawable image = methodThatGetsTheImage(fileUrl);
if (image != null) {
view.post(new Runnable() {
@Override
public void run() {
view.setImageDrawable(drawable);
}
});
}
}
});
}
他のヒント
また、それにもかかわらず(ドロップインソリューションを cwacサムネイルをチェックアウトすることができます)上記の単純なソリューションよりも少しオーバーヘッド有します。私は、ダウンロードにWebイメージを持っている偉大な成功はかなりのどこでそれを使用しました。あなたは基本的にそしてちょうどアンドロイドのリストをThumbnailAdapterであなたのListAdapterをラップ、アプリのいくつかのグローバルキャッシュ・オプションを設定します。あなたのリストの中imageviewsのID、およびアダプタのGetViewメソッドでimageviewsにsetTag(IMAGEURL)を呼び出して、それは残りの部分を処理します。
はい。あなたは、可能な限りUIスレッド上で実行しないようにしてください。あなたはgetViewメソッド()にいるときには、UIスレッドです。
:抜け出すためには、これを行いますnew Thread(new Runnable(){
public void run() {
// your code here
}}).start();
あなたは、このようなUIスレッドの上にいくつかの方法の行く裏にビューを変更する必要が続いたときます:
runOnUiThread(new Runnable(){
public void run() {
// your view-modifying code here
}});
..またはView.post()メカニズムを使用します。
あなたの例では何が起こるだろうと、画像が表示のために利用可能になる前にアイテムが画面に表示されるということです。私は何が起こっているかをユーザに示すために「ロード」スピナー、他のいくつかのプレースホルダを使用することをお勧めします。
あなたは簡略化され、デザインが順番にあるポイントに到達しますが、あなたは、この数倍気に入る練習の巣にすることができます。匿名クラスはメカニズムは独自の欠点を持つことができ、キャンセル非効率的なメモリ単位とすることなく、多数のスレッドをオフに発射することができます。
あなたは終了しましたgetViewメソッドの後に変更するビューの副作用()などいくつかの問題が発生することがあります。いくつかのビューは、その変更を有効にするために呼び出さ無効を()が必要な場合があります。あなたのgetViewメソッド()でビューをリサイクルしている場合にも注意してください、あなたはビューはまだあなたが適用されているコンテンツに使用されている時間によって、あなたのビュー変更のコードが実行されていることを確認する必要があります。 setTag()/のgetTag()を使用すると、後で必ずあなたのビューがリサイクルされていないにするためにチェックできるというデータのいくつかのIDを格納するためにここに便利です。