【问题标题】:Android load from URL to Bitmap #2Android 从 URL 加载到位图 #2
【发布时间】:2012-12-20 02:22:53
【问题描述】:

我无法根据以下答案从 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"/>

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

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

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

【问题讨论】:

    标签: android android-emulator bitmap


    【解决方案1】:

    当图像大小为 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);
    

    【讨论】:

      【解决方案2】:

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

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

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

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

      【讨论】:

        【解决方案3】:

        从 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");
        }
        

        【讨论】:

          猜你喜欢
          • 2012-02-18
          • 2015-07-22
          • 2016-06-20
          • 1970-01-01
          • 1970-01-01
          • 2015-06-22
          • 2016-11-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多