1

mp3 から直接画像を読み込んで、アプリで曲のタイトルと一緒に表示しています。プロセスをスムーズにするために、私は AsyncTask を使用してバックグラウンドで画像をロードしています。ゆっくりスクロールすると、画像が曲とともに正しい順序で表示されます。ただし、上下にすばやくスクロールすると、画像が2〜3秒間ごちゃごちゃになります(誤った順序で表示されるように)。2 ~ 3 秒後、注文は再び正常になります。どうすればこれを回避できますか? これが私のコードです:

public class TestAcitivity extends SherlockListActivity  {
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        ActionBar ab = getSupportActionBar();
        Uri sourceUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
        String [] proj = {MediaStore.Audio.Media._ID,MediaStore.Audio.Media.TITLE,MediaStore.Audio.Media.ALBUM_ID};
        CursorLoader cursorLoader = new CursorLoader(this, sourceUri,proj,
                                                        null, null, MediaStore.Audio.Media.TITLE);
        Cursor cursor = cursorLoader.loadInBackground();
        ListView lv = getListView();//(ListView)this.findViewById(R.id.listview);
        lv.setAdapter(new MyAdapter(this, cursor, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER));
    }
}
class MyAdapter extends CursorAdapter {

    private LayoutInflater mLayoutInflater;
    @SuppressWarnings("unused")
    private Context mContext;

    public MyAdapter(Context context, Cursor c, int flags) {
        super(context, c, flags);
        mContext = context;
        mLayoutInflater = LayoutInflater.from(context);
    }
    public void bindView(View view, Context context, Cursor cursor) {
        String title = cursor.getString(cursor.getColumnIndex(MediaStore.MediaColumns.TITLE));
        String album_id = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));
        TextView text = (TextView)view.findViewById(R.id.txtTitle);
        text.setText(title);
        if(Long.valueOf(album_id)>0)
        {
            Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
            Uri uri = ContentUris.withAppendedId(sArtworkUri, Integer.valueOf(album_id));
            new MyImageLoader(context,view).execute(uri);
        }
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        View v = mLayoutInflater.inflate(R.layout.row, parent, false);
        //bindView(v, context, cursor);
        return v;
    }
    private class MyImageLoader extends AsyncTask<Uri, Void, Bitmap>{
        Context context;
        View view;
        MyImageLoader(Context context,View view){
            this.context = context;
            this.view = view;
        }
        @Override
        protected Bitmap doInBackground(Uri... uri) {

            ContentResolver res = context.getContentResolver();
            InputStream in = null;
            try {
                in = res.openInputStream(uri[0]);
            } 
            catch (FileNotFoundException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            Bitmap artwork = BitmapFactory.decodeStream(in);

            return artwork;

        }
        protected void onPostExecute(Bitmap bmp){
            ImageView iv = (ImageView)view.findViewById(R.id.imgIcon);
            if(bmp!=null)
                iv.setImageBitmap(Bitmap.createScaledBitmap(bmp, 100, 100, false));
        }
    }
}

CursorAdapterにビットマップをロードするカスタムを使用していAsyncTaskます。

4

2 に答える 2

0

非同期更新の影響を受けるリストのソート順を制御しているものに関連している可能性があります。リスト ビューのレンダリング コードを混乱させるリスト項目のサイズの急速な変化である可能性があります。1 つの提案は、同じサイズのデフォルト (おそらく黒) の画像を各リスト項目に直接追加することです。次に、実際の画像が表示されたら、黒い画像を置き換えます。


編集:この問題は、Android が ViewItem/row をリサイクルし、非同期タスクと混同しているために発生しているようです。詳細といくつかの解決策については、このStackOverflow の質問を参照してください。

于 2013-02-23T13:02:11.097 に答える
0

Hack_on は正しいです。Andorid のエンジニアの 1 人が、ブログの中でこの問題について議論しています。

ただし、ListView 固有の動作により、現在の実装の問題が明らかになります。実際、メモリ効率の理由から、ListView はユーザーがスクロールしたときに表示されるビューをリサイクルします。リストを投げると、特定の ImageView オブジェクトが何度も使用されます。ImageView が表示されるたびに、イメージ ダウンロード タスクが正しくトリガーされ、最終的にイメージが変更されます。では、どこに問題があるのでしょうか。ほとんどの並列アプリケーションと同様に、重要な問題は順序にあります。この場合、ダウンロード タスクが開始された順序で完了するという保証はありません。その結果、リストに最終的に表示される画像は、たまたまダウンロードに時間がかかった以前のアイテムからのものである可能性があります。

ここにリンクがあります。彼は解決策も提供しています:

http://android-developers.blogspot.com/2010/07/multithreading-for-performance.html

于 2013-04-30T04:56:53.320 に答える