Android从URL加载到位图#2

时间:2013-01-05 23:32:47

标签: android android-emulator bitmap

我无法根据以下答案从Android上的网址加载位图:https://stackoverflow.com/a/8993175/1062794

我已将案例简化为绝对最小值:

public void loadBitmap(View view) {
    Bitmap b = getBitmapFromURL("http://upload.wikimedia.org/wikipedia/en/7/70/Example.png");
}

public Bitmap getBitmapFromURL(String src) {
    try {
        URL url = new URL(src);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.setDoInput(true);
        connection.connect();
        InputStream input = connection.getInputStream();
        Bitmap myBitmap = BitmapFactory.decodeStream(input);
        return myBitmap;
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}

我在清单中启用了互联网访问(我相信):

<uses-permission android:name="android.permission.INTERNET"/>

当我运行应用时,它会在尝试运行null时崩溃并显示connection.connect()个详细信息。单步执行我看到它试图从StrictMode.class抛出此错误:

if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
    throw new NetworkOnMainThreadException();
}

这是我尝试制作Android应用程序的第一天,因此我可能犯了一个明显的错误。我正在使用模拟器和Win7。

3 个答案:

答案 0 :(得分:4)

从Android 3.0开始,无法再直接从UI线程运行同步操作。如果您尝试直接在onCreate()方法中调用loadBitmap(View视图)方法,则在运行Android 3.0及更高版本的设备上运行时,应用程序将崩溃。因为loadBitmap()方法是同步的 - 也就是说,在下载图像之前它不会返回控件 - 直接调用它会冻结您的活动的UI。 Android 3.0及更高版本不允许这样做;所有同步代码必须使用 AsyncTask 类进行包装。使用AsyncTask,您可以在单独的线程中执行后台任务,然后在UI线程中返回结果。这样,您就可以执行后台操作,而无需处理复杂的线程问题。要调用loadBitamp()方法异步,需要将代码包装在AsyncTask类的子类中,如下所示:

private class DownloadImage extends AsyncTask<String, Void, Bitmap> {
    protected Bitmap  doInBackground(String... urls) {
    return getBitmapFromUrl(urls[0]);
    }
    protected void onPostExecute(Bitamp result) {
    ImageView img = (ImageView) findViewById(R.id.img);
    img.setImageBitmap(result);
    }
}

现在在onCreate()方法中创建一个AsyncTask类的新实例并执行它:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    new DownloadImage().execute("http://upload.wikimedia.org/wikipedia/en/7/70/Example.png");
}

答案 1 :(得分:2)

这是因为您尝试从ui线程访问互联网(更多信息here)。

创建一个新线程(如果你愿意,可以使用asyncTask,但任何其他线程创建方法就足够了)以便访问互联网,一旦位图准备就绪,如果你希望将它传递给ui线程显示它

另外,对于一个很好的位图处理示例,请阅读:

http://developer.android.com/training/displaying-bitmaps/index.html

答案 2 :(得分:0)

当图像大小为5 MG时,您的虚空将会崩溃。位图是堆叠RAM,因此采样20个图像* 5 = 100 mb。当你重新打开活动时,另外100 MB花费你的RAM和应用程序将崩溃。您可以在代码中添加以下行;

                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inPreferredConfig = Config.RGB_565;
                options.inSampleSize = 2;
                Bitmap myBitmap = BitmapFactory.decodeStream(input,rect,options);