我部分遵循http://android-developers.blogspot.de/2010/07/multithreading-for-performance.html从 url 下载图像并将其显示在 gridview 中。使用静态列表可以正常工作。
我正在尝试通过使用 jsoup 解析网页并创建我自己的 url 列表来从 web 中获取一些 url。该程序只是在启动时崩溃。
public class MainGridActivity extends Activity {
private ImageAdapter mAdapter;
private Bitmap mPlaceHolder;
private String [] mMangaList = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_grid);
downloadMangaImages();
GridView gridView = (GridView) findViewById(R.id.gridView);
mAdapter = new ImageAdapter(this);
setLoadingImage(R.drawable.empty_photo);
gridView.setAdapter(mAdapter);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_grid, menu);
return true;
}
/**
* sets a place holder bitmap while the actual bitmap is loading
*
* @param resId
*/
public void setLoadingImage(int resId) {
mPlaceHolder = BitmapFactory.decodeResource(getResources(), resId);
}
public void downloadMangaImages() {
try {
Document doc = Jsoup.connect("http://mangafox.me/directory/").get();
Element content = doc.getElementById("content");
Elements links = content.getElementsByTag("img");
mMangaList = new String[links.toArray().length];
int i = 0;
for(Element link : links) {
mMangaList[i] = link.attr("src");
i++;
}
} catch(IOException e) {}
}
private class ImageAdapter extends BaseAdapter {
private Context mContext;
public ImageAdapter (Context context) {
mContext = context;
}
@Override
public int getCount() {
return mMangaList.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup container) {
ImageView imageView;
if(convertView == null) {
imageView = new ImageView(mContext);
imageView.setLayoutParams(new GridView.LayoutParams(200,300));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
} else {
imageView = (ImageView) convertView;
}
loadImageToView(mMangaList[position],imageView);
return imageView;
}
}
public void loadImageToView(String url, ImageView imageView) {
final BitmapWorkerTask task;
final TaskReference taskReference;
if(url == null) {
return;
}
else if(cancelPotentialWork(url, imageView)) { // tries to cancel previous tasks on this imageView if possible
task = new BitmapWorkerTask(imageView);
taskReference = new TaskReference(getResources(),task, mPlaceHolder);
imageView.setImageDrawable(taskReference);
task.execute(url);
}
}
private static boolean cancelPotentialWork (String url, ImageView imageView) {
BitmapWorkerTask previousTask = getBitmapWorkerTask(imageView);
if(previousTask != null) {
String previousUrl = previousTask.url;
if(previousUrl == null || !previousUrl.equals(url)) {
previousTask.cancel(true);
} else {
return false; // since task is already in progress, let it finish
}
}
return true;
}
private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
if(imageView != null) {
final Drawable drawable = imageView.getDrawable();
if(drawable instanceof TaskReference) {
return ((TaskReference) drawable).getBitmapWorkerTask();
}
}
return null;
}
private class BitmapWorkerTask extends AsyncTask<String, Void, Bitmap> {
//Fields
private final WeakReference<ImageView> mImageViewReference;
private String url;
//constructors
public BitmapWorkerTask(ImageView imageView) {
mImageViewReference = new WeakReference<ImageView> (imageView);
}
//main body
@Override
protected Bitmap doInBackground(String ... urls) { //Image not found in memory cache so start processing image here
url = urls[0];
return downloadBitmapFromURL(url);
}
@Override
protected void onPostExecute(Bitmap bitmap) {
if(isCancelled()) {
bitmap = null;
}
if(mImageViewReference != null) {
ImageView imageView = mImageViewReference.get();
BitmapWorkerTask task = getBitmapWorkerTask(imageView);
if(this == task) {
imageView.setImageBitmap(bitmap);
}
}
}
public Bitmap downloadBitmapFromURL(String urlString) {
final int BUFFER_SIZE = 8 *1024;
HttpURLConnection conn = null;
InputStream is = null;
try {
final URL url = new URL(urlString);
conn = (HttpURLConnection) url.openConnection();
is = new BufferedInputStream(conn.getInputStream(), BUFFER_SIZE);
return BitmapFactory.decodeStream(is);
} catch(IOException e) {}
finally {
if(conn != null) {
conn.disconnect();
}
try {
if(is != null) {
is.close();
}
} catch (IOException e) {}
}
return null;
}
}
private class TaskReference extends BitmapDrawable {
private final WeakReference<BitmapWorkerTask> mBitmapWorkerTaskReference;
public TaskReference(Resources res, BitmapWorkerTask task, Bitmap placeHolder) {
super(res, placeHolder);
mBitmapWorkerTaskReference = new WeakReference<BitmapWorkerTask>(task);
}
public BitmapWorkerTask getBitmapWorkerTask(){
return mBitmapWorkerTaskReference.get();
}
}
}
日志猫
06-18 21:24:28.845: D/AbsListView(5721): Get MotionRecognitionManager
06-18 21:24:28.865: D/AndroidRuntime(5721): Shutting down VM
06-18 21:24:28.865: W/dalvikvm(5721): threadid=1: thread exiting with uncaught exception (group=0x40ccc2a0)
06-18 21:24:28.870: E/AndroidRuntime(5721): FATAL EXCEPTION: main
06-18 21:24:28.870: E/AndroidRuntime(5721): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.gridviewtest/com.gridviewtest.MainGridActivity}: android.os.NetworkOnMainThreadException
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.ActivityThread.access$600(ActivityThread.java:140)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.os.Handler.dispatchMessage(Handler.java:99)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.os.Looper.loop(Looper.java:137)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.ActivityThread.main(ActivityThread.java:4898)
06-18 21:24:28.870: E/AndroidRuntime(5721): at java.lang.reflect.Method.invokeNative(Native Method)
06-18 21:24:28.870: E/AndroidRuntime(5721): at java.lang.reflect.Method.invoke(Method.java:511)
06-18 21:24:28.870: E/AndroidRuntime(5721): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
06-18 21:24:28.870: E/AndroidRuntime(5721): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
06-18 21:24:28.870: E/AndroidRuntime(5721): at dalvik.system.NativeStart.main(Native Method)
06-18 21:24:28.870: E/AndroidRuntime(5721): Caused by: android.os.NetworkOnMainThreadException
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1118)
06-18 21:24:28.870: E/AndroidRuntime(5721): at java.net.InetAddress.lookupHostByName(InetAddress.java:385)
06-18 21:24:28.870: E/AndroidRuntime(5721): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
06-18 21:24:28.870: E/AndroidRuntime(5721): at java.net.InetAddress.getAllByName(InetAddress.java:214)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpConnection.<init>(HttpConnection.java:70)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpConnection.<init>(HttpConnection.java:50)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpConnection$Address.connect(HttpConnection.java:340)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpConnectionPool.get(HttpConnectionPool.java:87)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpConnection.connect(HttpConnection.java:128)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpEngine.openSocketConnection(HttpEngine.java:315)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpEngine.connect(HttpEngine.java:310)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:289)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:239)
06-18 21:24:28.870: E/AndroidRuntime(5721): at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
06-18 21:24:28.870: E/AndroidRuntime(5721): at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:425)
06-18 21:24:28.870: E/AndroidRuntime(5721): at org.jsoup.helper.HttpConnection$Response.execute(HttpConnection.java:410)
06-18 21:24:28.870: E/AndroidRuntime(5721): at org.jsoup.helper.HttpConnection.execute(HttpConnection.java:164)
06-18 21:24:28.870: E/AndroidRuntime(5721): at org.jsoup.helper.HttpConnection.get(HttpConnection.java:153)
06-18 21:24:28.870: E/AndroidRuntime(5721): at com.gridviewtest.MainGridActivity.downloadMangaImages(MainGridActivity.java:71)
06-18 21:24:28.870: E/AndroidRuntime(5721): at com.gridviewtest.MainGridActivity.onCreate(MainGridActivity.java:42)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.Activity.performCreate(Activity.java:5206)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094)
06-18 21:24:28.870: E/AndroidRuntime(5721): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
06-18 21:24:28.870: E/AndroidRuntime(5721): ... 11 more