0

我部分遵循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
4

1 回答 1

0

您需要downloadMangaImages();在后台线程中移动方法。AsyncTask是您的最佳选择。

类似于(盲编码):

String targetURL = ....
new AsyncTask<String, Void, String[]>(){
 protected String[] doInBackground(String ... args) {
  try {

            Document doc = Jsoup.connect("http://mangafox.me/directory/").get();

            Element content = doc.getElementById("content");
            Elements links = content.getElementsByTag("img");

            String[] mMangaList = new String[links.toArray().length];
            int i = 0;
            for(Element link : links) {
                mMangaList[i] = link.attr("src");
                i++;
            }
 return mMangaList;
        } catch(IOException e) {return null;}
 }
 protected void onPostExecute(String[] result) {
if(result != null) {
 // create the adapter and load it in list
}
}
}.execute(targetURL);
于 2013-06-18T20:34:00.390 回答