This simple app gets a tag from the user and display in a ListView first 10 Flicker images that match the tag. I used this simple tutorial, i just modified it so it can work with flicker search, instead of hard coded links. It works but somehow it loads images one upon another in some views. So user sees that in a view image changes for a while. And if user scrolls, it reloads them again. If it's a pointer issue, i couldn't resolve it. I changed static ViewHolder to a non-static class, but nothing changed. Why it happens and how can i fix it?
Main class:
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();
}
}
}
}
Adapter Class:
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
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;
}
}