├── .classpath
├── .gitignore
├── .project
├── AndroidManifest.xml
├── README.md
├── assets
├── .DS_Store
└── json_simple-1.1.jar
├── bin
├── TweetView.apk
├── classes.dex
├── com
│ └── example
│ │ ├── Example$Tweet.class
│ │ ├── Example.class
│ │ ├── ImageManager$BitmapDisplayer.class
│ │ ├── ImageManager$ImageQueue.class
│ │ ├── ImageManager$ImageQueueManager.class
│ │ ├── ImageManager$ImageRef.class
│ │ ├── ImageManager.class
│ │ ├── R$attr.class
│ │ ├── R$drawable.class
│ │ ├── R$id.class
│ │ ├── R$layout.class
│ │ ├── R$string.class
│ │ ├── R.class
│ │ ├── TweetItemAdapter$ViewHolder.class
│ │ └── TweetItemAdapter.class
└── resources.ap_
├── default.properties
├── gen
└── com
│ └── example
│ └── R.java
├── proguard.cfg
├── res
├── drawable-hdpi
│ └── icon.png
├── drawable-ldpi
│ └── icon.png
├── drawable-mdpi
│ └── icon.png
├── layout
│ ├── listitem.xml
│ └── main.xml
└── values
│ └── strings.xml
└── src
└── com
└── example
├── Example.java
├── ImageManager.java
└── TweetItemAdapter.java
/.classpath:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | TweetView
4 |
5 |
6 |
7 |
8 |
9 | com.android.ide.eclipse.adt.ResourceManagerBuilder
10 |
11 |
12 |
13 |
14 | com.android.ide.eclipse.adt.PreCompilerBuilder
15 |
16 |
17 |
18 |
19 | org.eclipse.jdt.core.javabuilder
20 |
21 |
22 |
23 |
24 | com.android.ide.eclipse.adt.ApkBuilder
25 |
26 |
27 |
28 |
29 |
30 | com.android.ide.eclipse.adt.AndroidNature
31 | org.eclipse.jdt.core.javanature
32 |
33 |
34 |
--------------------------------------------------------------------------------
/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## TweetView
2 |
3 | This project is an example Android Twitter feed reader app
4 | from the Codehenge Android development tutorial:
5 |
6 | http://www.codehenge.net/blog/
7 |
8 | It is designed as a learning aid, and written for illustrative purposes. This project was developed in Eclipse, and includes all associated files. I've also packaged in the open source simple-json library used in the example.
9 |
10 | This code is free as in both speech and beer. Feel free to fork, modify, or do anything you want with this code.
11 |
12 |
13 | [Associated Blog Post](http://www.codehenge.net/2011/06/android-development-tutorial-asynchronous-lazy-loading-and-caching-of-listview-images/)
14 |
--------------------------------------------------------------------------------
/assets/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/assets/.DS_Store
--------------------------------------------------------------------------------
/assets/json_simple-1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/assets/json_simple-1.1.jar
--------------------------------------------------------------------------------
/bin/TweetView.apk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/TweetView.apk
--------------------------------------------------------------------------------
/bin/classes.dex:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/classes.dex
--------------------------------------------------------------------------------
/bin/com/example/Example$Tweet.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/Example$Tweet.class
--------------------------------------------------------------------------------
/bin/com/example/Example.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/Example.class
--------------------------------------------------------------------------------
/bin/com/example/ImageManager$BitmapDisplayer.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/ImageManager$BitmapDisplayer.class
--------------------------------------------------------------------------------
/bin/com/example/ImageManager$ImageQueue.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/ImageManager$ImageQueue.class
--------------------------------------------------------------------------------
/bin/com/example/ImageManager$ImageQueueManager.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/ImageManager$ImageQueueManager.class
--------------------------------------------------------------------------------
/bin/com/example/ImageManager$ImageRef.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/ImageManager$ImageRef.class
--------------------------------------------------------------------------------
/bin/com/example/ImageManager.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/ImageManager.class
--------------------------------------------------------------------------------
/bin/com/example/R$attr.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/R$attr.class
--------------------------------------------------------------------------------
/bin/com/example/R$drawable.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/R$drawable.class
--------------------------------------------------------------------------------
/bin/com/example/R$id.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/R$id.class
--------------------------------------------------------------------------------
/bin/com/example/R$layout.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/R$layout.class
--------------------------------------------------------------------------------
/bin/com/example/R$string.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/R$string.class
--------------------------------------------------------------------------------
/bin/com/example/R.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/R.class
--------------------------------------------------------------------------------
/bin/com/example/TweetItemAdapter$ViewHolder.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/TweetItemAdapter$ViewHolder.class
--------------------------------------------------------------------------------
/bin/com/example/TweetItemAdapter.class:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/com/example/TweetItemAdapter.class
--------------------------------------------------------------------------------
/bin/resources.ap_:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/bin/resources.ap_
--------------------------------------------------------------------------------
/default.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system use,
7 | # "build.properties", and override values to adapt the script to your
8 | # project structure.
9 |
10 | # Project target.
11 | target=android-4
12 |
--------------------------------------------------------------------------------
/gen/com/example/R.java:
--------------------------------------------------------------------------------
1 | /* AUTO-GENERATED FILE. DO NOT MODIFY.
2 | *
3 | * This class was automatically generated by the
4 | * aapt tool from the resource data it found. It
5 | * should not be modified by hand.
6 | */
7 |
8 | package com.example;
9 |
10 | public final class R {
11 | public static final class attr {
12 | }
13 | public static final class drawable {
14 | public static final int icon=0x7f020000;
15 | }
16 | public static final class id {
17 | public static final int ListViewId=0x7f050003;
18 | public static final int avatar=0x7f050000;
19 | public static final int message=0x7f050002;
20 | public static final int username=0x7f050001;
21 | }
22 | public static final class layout {
23 | public static final int listitem=0x7f030000;
24 | public static final int main=0x7f030001;
25 | }
26 | public static final class string {
27 | public static final int app_name=0x7f040001;
28 | public static final int hello=0x7f040000;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/proguard.cfg:
--------------------------------------------------------------------------------
1 | -optimizationpasses 5
2 | -dontusemixedcaseclassnames
3 | -dontskipnonpubliclibraryclasses
4 | -dontpreverify
5 | -verbose
6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
7 |
8 | -keep public class * extends android.app.Activity
9 | -keep public class * extends android.app.Application
10 | -keep public class * extends android.app.Service
11 | -keep public class * extends android.content.BroadcastReceiver
12 | -keep public class * extends android.content.ContentProvider
13 | -keep public class * extends android.app.backup.BackupAgentHelper
14 | -keep public class * extends android.preference.Preference
15 | -keep public class com.android.vending.licensing.ILicensingService
16 |
17 | -keepclasseswithmembernames class * {
18 | native ;
19 | }
20 |
21 | -keepclasseswithmembernames class * {
22 | public (android.content.Context, android.util.AttributeSet);
23 | }
24 |
25 | -keepclasseswithmembernames class * {
26 | public (android.content.Context, android.util.AttributeSet, int);
27 | }
28 |
29 | -keepclassmembers enum * {
30 | public static **[] values();
31 | public static ** valueOf(java.lang.String);
32 | }
33 |
34 | -keep class * implements android.os.Parcelable {
35 | public static final android.os.Parcelable$Creator *;
36 | }
37 |
--------------------------------------------------------------------------------
/res/drawable-hdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/res/drawable-hdpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-ldpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/res/drawable-ldpi/icon.png
--------------------------------------------------------------------------------
/res/drawable-mdpi/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cacois/TweetView/1cc7eed35138046f64211d78354e45dc4dbac701/res/drawable-mdpi/icon.png
--------------------------------------------------------------------------------
/res/layout/listitem.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
16 |
21 |
25 |
30 |
31 |
--------------------------------------------------------------------------------
/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
12 |
--------------------------------------------------------------------------------
/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Hello World, Example!
4 | CustomListViewExample
5 |
6 |
--------------------------------------------------------------------------------
/src/com/example/Example.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import java.util.ArrayList;
4 |
5 | import org.apache.http.client.HttpClient;
6 | import org.apache.http.client.ResponseHandler;
7 | import org.apache.http.client.methods.HttpGet;
8 | import org.apache.http.impl.client.BasicResponseHandler;
9 | import org.apache.http.impl.client.DefaultHttpClient;
10 | import org.json.simple.JSONArray;
11 | import org.json.simple.JSONObject;
12 | import org.json.simple.parser.JSONParser;
13 |
14 | import android.app.Activity;
15 | import android.graphics.Bitmap;
16 | import android.os.Bundle;
17 | import android.util.Log;
18 | import android.widget.ListView;
19 |
20 | public class Example extends Activity {
21 |
22 | public Bitmap placeholder;
23 |
24 | @Override
25 | public void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.main);
28 |
29 | ArrayList tweets = getTweets("android", 1);
30 |
31 | ListView listView = (ListView) findViewById(R.id.ListViewId);
32 | listView.setAdapter(new TweetItemAdapter(this, R.layout.listitem, tweets));
33 | }
34 |
35 | public ArrayList getTweets(String searchTerm, int page) {
36 | String searchUrl = "http://search.twitter.com/search.json?q=@"
37 | + searchTerm + "&rpp=100&page=" + page;
38 |
39 | ArrayList tweets = new ArrayList();
40 |
41 | HttpClient client = new DefaultHttpClient();
42 | HttpGet get = new HttpGet(searchUrl);
43 |
44 | ResponseHandler responseHandler = new BasicResponseHandler();
45 |
46 | String responseBody = null;
47 | try{
48 | responseBody = client.execute(get, responseHandler);
49 | }catch(Exception ex) {
50 | ex.printStackTrace();
51 | }
52 |
53 | JSONObject jsonObject = null;
54 | JSONParser parser=new JSONParser();
55 |
56 | try {
57 | Object obj = parser.parse(responseBody);
58 | jsonObject=(JSONObject)obj;
59 |
60 | }catch(Exception ex){
61 | Log.v("TEST","Exception: " + ex.getMessage());
62 | }
63 |
64 | JSONArray arr = null;
65 |
66 | try {
67 | Object j = jsonObject.get("results");
68 | arr = (JSONArray)j;
69 | }catch(Exception ex){
70 | Log.v("TEST","Exception: " + ex.getMessage());
71 | }
72 |
73 | for(Object t : arr) {
74 | Tweet tweet = new Tweet(
75 | ((JSONObject)t).get("from_user").toString(),
76 | ((JSONObject)t).get("text").toString(),
77 | ((JSONObject)t).get("profile_image_url").toString()
78 | );
79 | tweets.add(tweet);
80 | }
81 |
82 | return tweets;
83 | }
84 |
85 | /** Classes **/
86 |
87 | public class Tweet {
88 | public String username;
89 | public String message;
90 | public String image_url;
91 | public Boolean usernameSet = false;
92 | public Boolean messageSet = false;
93 | public Boolean imageSet = false;
94 | public Bitmap avatar;
95 |
96 | public Tweet(String username, String message, String url) {
97 | this.username = username;
98 | this.message = message;
99 | this.image_url = url;
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/src/com/example/ImageManager.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileOutputStream;
6 | import java.io.FileReader;
7 | import java.io.IOException;
8 | import java.lang.ref.SoftReference;
9 | import java.net.URL;
10 | import java.net.URLConnection;
11 | import java.text.DateFormat;
12 | import java.text.SimpleDateFormat;
13 | import java.util.HashMap;
14 | import java.util.Stack;
15 |
16 | import android.app.Activity;
17 | import android.content.Context;
18 | import android.graphics.Bitmap;
19 | import android.graphics.BitmapFactory;
20 | import android.widget.ImageView;
21 |
22 | public class ImageManager {
23 |
24 | private long cacheDuration;
25 | private DateFormat mDateFormatter;
26 |
27 | private HashMap> imageMap = new HashMap>();
28 |
29 | private File cacheDir;
30 | private ImageQueue imageQueue = new ImageQueue();
31 | private Thread imageLoaderThread = new Thread(new ImageQueueManager());
32 |
33 | public ImageManager(Context context, long _cacheDuration) {
34 |
35 | cacheDuration = _cacheDuration;
36 | //TODO Make this match the date format of your server
37 | mDateFormatter = new SimpleDateFormat("EEE',' dd MMM yyyy HH:mm:ss zzz");
38 |
39 | // Make background thread low priority, to avoid affecting UI performance
40 | imageLoaderThread.setPriority(Thread.NORM_PRIORITY-1);
41 |
42 | // Find the dir to save cached images
43 | String sdState = android.os.Environment.getExternalStorageState();
44 | if (sdState.equals(android.os.Environment.MEDIA_MOUNTED)) {
45 | File sdDir = android.os.Environment.getExternalStorageDirectory();
46 | cacheDir = new File(sdDir,"data/codehenge");
47 |
48 | } else {
49 | cacheDir = context.getCacheDir();
50 | }
51 |
52 | if (!cacheDir.exists()) {
53 | cacheDir.mkdirs();
54 | }
55 | }
56 |
57 | public void displayImage(String url, ImageView imageView, int defaultDrawableId) {
58 |
59 | if(imageMap.containsKey(url)) {
60 | imageView.setImageBitmap(imageMap.get(url).get());
61 |
62 | } else {
63 | queueImage(url, imageView, defaultDrawableId);
64 | imageView.setImageResource(defaultDrawableId);
65 | }
66 | }
67 |
68 | private void queueImage(String url, ImageView imageView, int defaultDrawableId) {
69 | // This ImageView might have been used for other images, so we clear
70 | // the queue of old tasks before starting.
71 | imageQueue.Clean(imageView);
72 | ImageRef p = new ImageRef(url, imageView, defaultDrawableId);
73 |
74 | synchronized(imageQueue.imageRefs) {
75 | imageQueue.imageRefs.push(p);
76 | imageQueue.imageRefs.notifyAll();
77 | }
78 |
79 | // Start thread if it's not started yet
80 | if(imageLoaderThread.getState() == Thread.State.NEW) {
81 | imageLoaderThread.start();
82 | }
83 | }
84 |
85 | private Bitmap getBitmap(String url) {
86 |
87 | try {
88 | URLConnection openConnection = new URL(url).openConnection();
89 |
90 | String filename = String.valueOf(url.hashCode());
91 |
92 | File bitmapFile = new File(cacheDir, filename);
93 | Bitmap bitmap = BitmapFactory.decodeFile(bitmapFile.getPath());
94 |
95 | long currentTimeMillis = System.currentTimeMillis();
96 |
97 | // Is the bitmap in our cache?
98 | if (bitmap != null) {
99 |
100 | // Has it expired?
101 | long bitmapTimeMillis = bitmapFile.lastModified();
102 | if ( (currentTimeMillis - bitmapTimeMillis) < cacheDuration ) {
103 | return bitmap;
104 | }
105 |
106 | // Check also if it was modified on the server before downloading it
107 | String lastMod = openConnection.getHeaderField("Last-Modified");
108 | long lastModTimeMillis = mDateFormatter.parse(lastMod).getTime();
109 |
110 | if ( lastModTimeMillis <= bitmapTimeMillis ) {
111 |
112 | //Discard the connection and return the cached version
113 | return bitmap;
114 | }
115 | }
116 |
117 | // Nope, have to download it
118 | bitmap = BitmapFactory.decodeStream(openConnection.getInputStream());
119 | // save bitmap to cache for later
120 | writeFile(bitmap, bitmapFile);
121 |
122 | return bitmap;
123 |
124 | } catch (Exception ex) {
125 | ex.printStackTrace();
126 | return null;
127 | }
128 | }
129 |
130 | private void writeFile(Bitmap bmp, File f) {
131 | FileOutputStream out = null;
132 |
133 | try {
134 | out = new FileOutputStream(f);
135 | bmp.compress(Bitmap.CompressFormat.PNG, 80, out);
136 | } catch (Exception e) {
137 | e.printStackTrace();
138 | }
139 | finally {
140 | try { if (out != null ) out.close(); }
141 | catch(Exception ex) {}
142 | }
143 | }
144 |
145 | /** Classes **/
146 |
147 | private class ImageRef {
148 | public String url;
149 | public ImageView imageView;
150 | public int defDrawableId;
151 |
152 | public ImageRef(String u, ImageView i, int defaultDrawableId) {
153 | url=u;
154 | imageView=i;
155 | defDrawableId = defaultDrawableId;
156 | }
157 | }
158 |
159 | //stores list of images to download
160 | private class ImageQueue {
161 | private Stack imageRefs =
162 | new Stack();
163 |
164 | //removes all instances of this ImageView
165 | public void Clean(ImageView view) {
166 |
167 | for(int i = 0 ;i < imageRefs.size();) {
168 | if(imageRefs.get(i).imageView == view)
169 | imageRefs.remove(i);
170 | else ++i;
171 | }
172 | }
173 | }
174 |
175 | private class ImageQueueManager implements Runnable {
176 | @Override
177 | public void run() {
178 | try {
179 | while(true) {
180 | // Thread waits until there are images in the
181 | // queue to be retrieved
182 | if(imageQueue.imageRefs.size() == 0) {
183 | synchronized(imageQueue.imageRefs) {
184 | imageQueue.imageRefs.wait();
185 | }
186 | }
187 |
188 | // When we have images to be loaded
189 | if(imageQueue.imageRefs.size() != 0) {
190 | ImageRef imageToLoad;
191 |
192 | synchronized(imageQueue.imageRefs) {
193 | imageToLoad = imageQueue.imageRefs.pop();
194 | }
195 |
196 | Bitmap bmp = getBitmap(imageToLoad.url);
197 | imageMap.put(imageToLoad.url, new SoftReference(bmp));
198 | Object tag = imageToLoad.imageView.getTag();
199 |
200 | // Make sure we have the right view - thread safety defender
201 | if(tag != null && ((String)tag).equals(imageToLoad.url)) {
202 | BitmapDisplayer bmpDisplayer =
203 | new BitmapDisplayer(bmp, imageToLoad.imageView, imageToLoad.defDrawableId);
204 |
205 | Activity a =
206 | (Activity)imageToLoad.imageView.getContext();
207 |
208 | a.runOnUiThread(bmpDisplayer);
209 | }
210 | }
211 |
212 | if(Thread.interrupted())
213 | break;
214 | }
215 | } catch (InterruptedException e) {}
216 | }
217 | }
218 |
219 | //Used to display bitmap in the UI thread
220 | private class BitmapDisplayer implements Runnable {
221 | Bitmap bitmap;
222 | ImageView imageView;
223 | int defDrawableId;
224 |
225 | public BitmapDisplayer(Bitmap b, ImageView i, int defaultDrawableId) {
226 | bitmap=b;
227 | imageView=i;
228 | defDrawableId = defaultDrawableId;
229 | }
230 |
231 | public void run() {
232 | if(bitmap != null)
233 | imageView.setImageBitmap(bitmap);
234 | else
235 | imageView.setImageResource(defDrawableId);
236 | }
237 | }
238 | }
--------------------------------------------------------------------------------
/src/com/example/TweetItemAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example;
2 |
3 | import java.util.ArrayList;
4 |
5 | import com.example.Example.Tweet;
6 |
7 | import android.app.Activity;
8 | import android.content.Context;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.ArrayAdapter;
13 | import android.widget.ImageView;
14 | import android.widget.TextView;
15 |
16 | public class TweetItemAdapter extends ArrayAdapter {
17 | private ArrayList tweets;
18 | private Activity activity;
19 | public ImageManager imageManager;
20 |
21 | public TweetItemAdapter(Activity a, int textViewResourceId, ArrayList tweets) {
22 | super(a, textViewResourceId, tweets);
23 | this.tweets = tweets;
24 | activity = a;
25 |
26 | imageManager =
27 | new ImageManager(activity.getApplicationContext());
28 | }
29 |
30 | public static class ViewHolder{
31 | public TextView username;
32 | public TextView message;
33 | public ImageView image;
34 | }
35 |
36 | @Override
37 | public View getView(int position, View convertView, ViewGroup parent) {
38 | View v = convertView;
39 | ViewHolder holder;
40 | if (v == null) {
41 | LayoutInflater vi =
42 | (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
43 | v = vi.inflate(R.layout.listitem, null);
44 | holder = new ViewHolder();
45 | holder.username = (TextView) v.findViewById(R.id.username);
46 | holder.message = (TextView) v.findViewById(R.id.message);
47 | holder.image = (ImageView) v.findViewById(R.id.avatar);
48 | v.setTag(holder);
49 | }
50 | else
51 | holder=(ViewHolder)v.getTag();
52 |
53 | final Tweet tweet = tweets.get(position);
54 | if (tweet != null) {
55 | holder.username.setText(tweet.username);
56 | holder.message.setText(tweet.message);
57 | holder.image.setTag(tweet.image_url);
58 | imageManager.displayImage(tweet.image_url, activity, holder.image);
59 | }
60 | return v;
61 | }
62 | }
--------------------------------------------------------------------------------