1

我无法根据此答案从 Android 上的 url 加载位图: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。

4

3 回答 3

4

从 Android 3.0 开始,同步操作不再可以直接从 UI 线程运行。如果您尝试直接在 onCreate() 方法中调用 loadBitmap(View 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");
}
于 2013-01-05T23:51:55.527 回答
2

这是因为您正试图从 ui 线程访问互联网(更多信息在这里)。

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

此外,对于一个很好的位图处理示例,请阅读以下内容:

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

于 2013-01-05T23:34:49.177 回答
0

当图像大小为 5 MG 时,您的 void 将崩溃。位图正在堆叠 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);
于 2013-09-30T10:28:31.883 回答