このシンプルなアプリケーションは、ユーザーからタグを取得し、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;
}
}
と '' 'AsynkTask'' 'は再利用されたビットマップへの参照を持っています。新しいアイテムが作成されたときにタスクをキャンセルする方法や、 '' 'AsyncTask'''からImageViewの参照を削除する方法を見つける必要があります。 – danypata
グライドのような画像ローダーライブラリを使用すると、非同期の読み込みを処理し、画像をキャッシュして、ユーザーがスクロールしたときに再度読み込まないようにします –