2016-05-12 28 views
0

このシンプルなアプリケーションは、ユーザーからタグを取得し、ListViewに最初に10個のタグに一致するちらつき画像を表示します。 thisシンプルチュートリアルを使用しました。ハードコードされたリンクではなく、ちらつき検索で動作するように修正しました。それは動作しますが、どういうわけか、いくつかのビューで画像を重ねて読み込みます。そのため、ユーザーはビューの画像がしばらく変化しているのを確認します。また、ユーザーがスクロールすると、再度読み込まれます。それがポインタの問題なら、私はそれを解決することができませんでした。静的なViewHolderを静的でないクラスに変更しましたが、何も変更されませんでした。なぜそれが起こり、どのように私はそれを修正することができますか?ListViewはビュー内で画像を重ねて表示します

メインクラス:

public class FlickerSearchMain extends AppCompatActivity implements AdapterView.OnItemClickListener, View.OnClickListener{ 
     private EditText tag; 
     private Button send; 
     private ListView listView; 
     ArrayList<ListItem> listData; 

     @Override 
     protected void onCreate(Bundle savedInstanceState) { 
      super.onCreate(savedInstanceState); 
      setContentView(R.layout.activity_flicker_search_main); 

      send = (Button) findViewById(R.id.send_button); 
      send.setOnClickListener(this); 
      tag = (EditText) findViewById(R.id.tag_input); 

      //ArrayList<ListItem> listData = getListData(); 
      listView = (ListView) findViewById(R.id.list); 
      listView.setOnItemClickListener(this); 


     } 

     @Override 
     public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 

      int itemPosition = position; 
      Toast.makeText(getApplicationContext(), 
        "Position :"+ itemPosition, Toast.LENGTH_SHORT) 
        .show(); 
     } 


     @Override 
     public void onClick(View v) { 
      if(v == send){ 
       String input = tag.getText().toString(); 
       new FlickerRequest(this).execute(input); 
      } 
     } 


     private class FlickerRequest extends AsyncTask<String, Void, ArrayList<ListItem>>{ 
      ArrayList<ListItem> elements_list; 
      Context context; 

      public FlickerRequest(Context context){ 
       this.context = context; 
       this.elements_list = new ArrayList<ListItem>(); 

      } 

      @Override 
      protected ArrayList<ListItem> doInBackground(String... params) { 
       String tag = params[0]; 

       int SIZE = 10; 
       URL flicker; 
       URLConnection urlcon; 
       BufferedReader in = null; 

       try { 
        flicker = new URL("https://api.flickr.com/services/feeds/photos_public.gne?tags=" 
          + tag + "&format=json"); 
        urlcon = flicker.openConnection(); 
        in = new BufferedReader(new InputStreamReader(urlcon.getInputStream())); 

        String inputLine; 
        StringBuilder strbuilder = new StringBuilder(); 

        in.skip(15); 

        while ((inputLine = in.readLine()) != null) 
         strbuilder.append(inputLine); 

        in.close(); 

        JSONObject job = new JSONObject(strbuilder.toString()); 
        JSONArray items = job.getJSONArray("items"); 

        for(int i=0; i<SIZE; i++) { 
         JSONObject item = items.getJSONObject(i); 
         ListItem newdata = new ListItem(); 
         newdata.setHeadline(item.getString("title")); 
         newdata.setAuthor(item.getString("author")); 
         newdata.setDate(item.getString("date_taken")); 
         newdata.setUrl(item.getJSONObject("media").getString("m")); 

         elements_list.add(newdata); 
        } 

       } catch (MalformedURLException e) { 
        e.printStackTrace(); 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } catch (JSONException e) { 
        e.printStackTrace(); 
       } 

       return elements_list; 
      } 

      protected void onPostExecute(ArrayList<ListItem> result) { 
       if(listData == null) { 
        listData = result; 
        listView.setAdapter(new FlickerAdapter(context, listData)); 
       } 
       else{ 
        listData = result; 
        ((BaseAdapter) listView.getAdapter()).notifyDataSetChanged(); 
       } 

      } 

     } 
    } 

アダプタクラス:

public class FlickerAdapter extends BaseAdapter { 
     private ArrayList<ListItem> listData; 
     private LayoutInflater layoutInflater; 

     public FlickerAdapter(Context context, ArrayList<ListItem> listData) { 
      this.listData = listData; 
      layoutInflater = LayoutInflater.from(context); 
     } 

     @Override 
     public int getCount() { 
      return listData.size(); 
     } 

     @Override 
     public Object getItem(int position) { 
      return listData.get(position); 
     } 

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

     public View getView(int position, View convertView, ViewGroup parent) { 
      ViewHolder holder; 
      if (convertView == null) { 
       convertView = layoutInflater.inflate(R.layout.list_row_layout, null); 
       holder = new ViewHolder(); 
       holder.headlineView = (TextView) convertView.findViewById(R.id.title); 
       holder.authorView = (TextView) convertView.findViewById(R.id.author); 
       holder.dateView = (TextView) convertView.findViewById(R.id.date); 
       holder.imageView = (ImageView) convertView.findViewById(R.id.image); 
       convertView.setTag(holder); 

      } else { 
       holder = (ViewHolder) convertView.getTag(); 
      } 

      ListItem newsItem = listData.get(position); 
      holder.headlineView.setText(newsItem.getHeadline()); 
      holder.authorView.setText("By, " + newsItem.getAuthor()); 
      holder.dateView.setText(newsItem.getDate()); 

      if (holder.imageView != null) { 
       new ImageDownloaderTask(holder.imageView).execute(newsItem.getUrl()); 
      } 

      return convertView; 
     } 

     static class ViewHolder { 
      TextView headlineView; 
      TextView authorView; 
      TextView dateView; 
      ImageView imageView; 
     } 
    } 

AsynTask ImageLoaderクラス

class ImageDownloaderTask extends AsyncTask<String, Void, Bitmap> { 
     private final WeakReference<ImageView> imageViewReference; 

     public ImageDownloaderTask(ImageView imageView) { 
      imageViewReference = new WeakReference<ImageView>(imageView); 
     } 

     @Override 
     protected Bitmap doInBackground(String... params) { 
      return downloadBitmap(params[0]); 
     } 



     @Override 
     protected void onPostExecute(Bitmap bitmap) { 
      if (isCancelled()) { 
       bitmap = null; 
      } 

      if (imageViewReference != null) { 
       ImageView imageView = imageViewReference.get(); 
       if (imageView != null) { 
        if (bitmap != null) { 
         imageView.setImageBitmap(bitmap); 
        } else { 
         //Drawable placeholder = imageView.getContext().getResources().getDrawable(R.drawable.penguin); 
         //imageView.setImageDrawable(placeholder); 
        } 
       } 

      } 
     } 

     private Bitmap downloadBitmap(String url) { 
      HttpURLConnection urlConnection = null; 
      try { 
       URL uri = new URL(url); 
       urlConnection = (HttpURLConnection) uri.openConnection(); 

       int statusCode = urlConnection.getResponseCode(); 
       if (statusCode != HttpURLConnection.HTTP_OK) { 
        return null; 
       } 

       InputStream inputStream = urlConnection.getInputStream(); 
       if (inputStream != null) { 
        Bitmap bitmap = BitmapFactory.decodeStream(inputStream); 
        return bitmap; 
       } 
      } catch (Exception e) { 
       urlConnection.disconnect(); 
       Log.w("ImageDownloader", "Error downloading image from " + url); 
      } finally { 
       if (urlConnection != null) { 
        urlConnection.disconnect(); 
       } 
      } 
      return null; 
     } 
    } 
+1

と '' 'AsynkTask'' 'は再利用されたビットマップへの参照を持っています。新しいアイテムが作成されたときにタスクをキャンセルする方法や、 '' 'AsyncTask'''からImageViewの参照を削除する方法を見つける必要があります。 – danypata

+0

グライドのような画像ローダーライブラリを使用すると、非同期の読み込みを処理し、画像をキャッシュして、ユーザーがスクロールしたときに再度読み込まないようにします –

答えて

0

あなたはImageViewを充填されたタスクが最もあることを確認する必要があります現在のタスクはImageViewです。タスクは、ImageViewがリサイクルされるまで完了できません。ここで

は、私がやったことだ:あなたのリソースに

 if (holder.imageView != null) { 
      Drawable placeholder = holder.imageView.getContext().getResources().getDrawable(R.drawable.penguin); 
      holder.imageView.setImageDrawable(placeholder); 

      ImageDownloaderTask task = new ImageDownloaderTask(holder.imageView); 
      holder.imageView.setTag(R.id.tag_key, task); 
      task.execute(newsItem.getUrl()); 
     } 

...

@Override 
    protected void onPostExecute(Bitmap bitmap) { 
     if (isCancelled()) { 
      bitmap = null; 
     } 

     if (bitmap != null && imageViewReference != null) { 
      ImageView imageView = imageViewReference.get(); 
      if (imageView != null && imageView.getTag(R.id.tag_key) == this) { 
       imageView.setImageBitmap(bitmap); 
       imageView.setTag(R.id.tag_key, null); 
      } 
     } 
    } 

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <item name="tag_key" type="id" /> 
</resources> 
あなたのセルが再利用されているためだ
+0

答えがありがたいですが、task.executeの戻り値を割り当てることはできません)をタスクに割り当てます。私はこのコードを 'ImgDTask task = new ImgDTask(holder.imageView);に変更するだけでこのコードをテストしました。この時間の画像は非常に遅くロードされ、スクロールすると、それらは消えて最近ロードされます。すべての画像の代わりにプレースホルダを見るのは少し醜いです。 – user3717434

+0

良い悲しみ、私はIDEなしで作業コードを書くことができません。正しいコードへの回答を更新する。だから、それは理想的な解決策ではありませんが、間違った画像が表示されるという問題を解決します。次のステップは、画像のLRUCacheを設定することです。ユーザーが再びスクロールアップしたときに画像をリロードする必要はありません。または、あなたは@ChristianStengelが言ったことをすることができます:グライドまたはピカソを使用して、それで済ませてください。 –

+0

誰もIDEなしで作業コードを書くことはできません:)とにかくおかげで、私はそれを試してみましょう。 – user3717434

関連する問題