2015-03-26 5 views
0

У меня есть фрагмент с GridView с ImageViews в качестве предметов. Количество ячеек составляет около 25.Загрузите по одному товару за один раз от AsyncTask

Для каждого изображения у меня есть запрос сервера по идентификатору. Таким образом, его 25 запросов сервера. Делает 2-3 секунды.

Как я могу получить одно изображение за раз и динамически установить его как содержимое ячейки? И каждая ячейка, у которой еще нет изображения, должна содержать ProgressBar.

Что я сейчас: Я пытаюсь загрузить вещи в AsyncTask и вернуть Bitmap массив обратно в UI потоке. Но я не знаю, как это сделать для каждого изображения. Мой GridView появляется только после загрузки ВСЕХ изображений. И это должно быть видно сначала с 25 элементами, которые содержат ProgressBars и без изображений.


код код

осколком onCreate():

@Override 
public void onCreate(Bundle savedInstanceState) { 
    ... 

    mItems = new Bitmap[dataChannelsList.size()]; 

    try { 
    //starting AsyncTask 
     mItems = new LoadImageAsyncTask(dataChannelsList).execute().get(); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 
} 

LoadImageAsyncTask:

private class LoadImageAsyncTask extends AsyncTask<Bitmap[], Void, Bitmap[]> { 
    private ArrayList<DataChannels> dataChannelsList; 
    private Bitmap[] bitmapList; 

    public LoadImageAsyncTask(ArrayList<DataChannels> dataChannelsList) { 
     this.dataChannelsList = dataChannelsList; 

     bitmapList = new Bitmap[dataChannelsList.size()]; 
    } 

    protected void onPreExecute() { 
     super.onPreExecute(); 
    } 

    protected Bitmap[] doInBackground(Bitmap[]... params) { 
     for (int i = 0; i < dataChannelsList.size(); i++) { 
      bitmapList[i] = getChannelImg(dataChannelsList.get(i).getId()); 
     } 
     return bitmapList; 
    } 


    protected void onPostExecute(Bitmap[] param) { 
     super.onPostExecute(param); 
    } 

    private Bitmap getChannelImg(String id) { 
     ...returns Bitmap image by id 
    } 

} 

GridView адаптер:

public class GridViewAdapter extends BaseAdapter { 
    private Context mContext; 
    private Bitmap[] mItems; 

    public GridViewAdapter(Context context, Bitmap[] items) { 
     mContext = context; 
     mItems = items; 
    } 

    @Override 
    public int getCount() { 
     return mItems.length; 
    } 

    @Override 
    public Object getItem(int position) { 
     return mItems[position]; 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ViewHolder viewHolder; 

     if (convertView == null) { 
      // inflate the GridView item layout 
      LayoutInflater inflater = LayoutInflater.from(mContext); 
      convertView = inflater.inflate(R.layout.gridview_item, parent, false); 

      // initialize the view holder 
      viewHolder = new ViewHolder(); 
      viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.imageview_channelIcon); 
      viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar_load_image); 
      convertView.setTag(viewHolder); 
     } else { 
      // recycle the already inflated view 
      viewHolder = (ViewHolder) convertView.getTag(); 
     } 

     // update the item view 
     Bitmap item = mItems[position]; 

     //hide progress bar and bring image to top 
     viewHolder.progressBar.setVisibility(View.GONE); 
     viewHolder.ivIcon.setImageBitmap(item); 
     return convertView; 
    } 

} 

private static class ViewHolder { 
    ImageView ivIcon; 
    ProgressBar progressBar; 
} 

Ребята, мне очень нужна ваша помощь. Сообщите, требуется ли еще какой-либо код или объяснения.

+1

проверить t Picasso http://stackoverflow.com/questions/22330772/why-use-android-picasso-library-to-download-images или, по крайней мере, рассмотреть решение с открытым исходным кодом, подобное этому, чтобы узнать – CSmith

+0

Вы должны вызвать imageLoaderTask onGetView() метод адаптера. Также загрузку задачи загрузчика следует параметризовать и вызывать адаптером с помощью image_id. – kgnkbyl

ответ

3

Вы можете использовать publishProgress() для этого вызвать onProgressUpdate()

Так что в вашем for loop что-то вроде

for (int i = 0; i < dataChannelsList.size(); i++) { 
     // create a variable for the current bitmap 
     Bitmap curBitmap = getChannelImg(dataChannelsList.get(i).getId()); 
     // add it to your list 
     bitmapList[i] = curBitmap; 
     // and pass it along 
     publishProgress(curBitmap); 
    } 

, то вам нужно будет переопределить onProgressUpdate() который вызывается publishProgress()

@Override 
public void onProgressUpdate(Bitmap...progress) { 
    /* add the bitmap to your list you're using for your adapter here 
    * and call notifyDataSetChanged() on your adapter 
    */ 
} 

Затем вам нужно будет изменить свою асинтезу на

private class LoadImageAsyncTask extends AsyncTask<Bitmap[], Bitmap, Bitmap[]> { 

Вы также не хотите звонить .get() на вашем AsyncTask, потому что it is a blocking call

что-то похожее на это должно дать вам то, что вы хотите.

Альтернативы

Однако, есть много libraries that can do the work for you and give you benefits.

+0

Спасибо за хорошее объяснение и советы! – AnZ

1
@Override 
public void onCreate(Bundle savedInstanceState) { 
    ... 

    mItems = new Bitmap[dataChannelsList.size()]; 
    GridView grid=// declare your gridview; 
GridViewAdapter adapter=new GridViewAdapter(activityname.this,mItems); 
grid.setAdapter(adapter); 

    try { 
    //starting AsyncTask here 

    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } catch (ExecutionException e) { 
     e.printStackTrace(); 
    } 
} 

и в assynctask

protected void onPostExecute(Bitmap[] param) { 
     super.onPostExecute(param); 
     adapter.notifydatasetchanged; 

// adapter should be declared as class variable,so that it can be used here.or else pass adapter variable as actual parameter to assynctask constructor 

    } 

для прогресс бар Я думаю, что вы делаете правильно изменить адаптер класса

@Override 
    public int getCount() { 
     return 25;// the size you want 
    } 

внутри метода GetView

@Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     ViewHolder viewHolder; 

int currentposition=position; 
     if (convertView == null) { 
      // inflate the GridView item layout 
      LayoutInflater inflater = LayoutInflater.from(mContext); 
      convertView = inflater.inflate(R.layout.gridview_item, parent, false); 

      // initialize the view holder 
      viewHolder = new ViewHolder(); 
      viewHolder.ivIcon = (ImageView) convertView.findViewById(R.id.imageview_channelIcon); 
      viewHolder.progressBar = (ProgressBar) convertView.findViewById(R.id.progress_bar_load_image); 
      viewHolder.ivIcon.setTag(currentposition); 
      convertView.setTag(viewHolder); 
     } else { 
      // recycle the already inflated view 
      viewHolder = (ViewHolder) convertView.getTag(); 
     } 

     // update the item view 
     Bitmap item = mItems[position]; 

     //hide progress bar and bring image to top 

if(Integer.parseInt(viewHolder.ivIcon.getTag().toString())>mItems.size()){ 
     viewHolder.progressBar.setVisibility(View.VISIBLE); 
viewHolder.ivIcon.setVisibility(View.VISIBLE); 
} 
else{ 
viewHolder.progressBar.setVisibility(View.INVISIBLE); 
viewHolder.ivIcon.setVisibility(View.INVISIBLE); 

} 
     viewHolder.ivIcon.setImageBitmap(item); 
     return convertView; 
    } 

} 
+0

Это никогда не сработает. Не используйте .get() в AsyncTask. – greenapps

+0

@greenapps PLS еще раз проверьте код в порядке ... и это не моя кодолина. –

+0

Почему вы удалили код для вызова asynctask? Далее этот код ничего не делает с загрузкой сразу или по одному. Так что вы решаете? – greenapps

Смежные вопросы