在NetworkOnMainThreadException中将URL转换为位图

3

我想要动态地从特定的URL添加图像到线性布局中。在运行代码时,我遇到了错误“Unable to start activity ComponentInfo: android.os.NetworkOnMainThreadException at com.example.star.example.CompinfoActivity.getBitmapFromURL(CompinfoActivity.java:70) at com.example.star.example.CompinfoActivity.insertPhoto(CompinfoActivity.java:50) at com.example.star.example.CompinfoActivity.onCreate(CompinfoActivity.java:38)”。请帮忙看一下。以下是我的活动代码。

public class CompinfoActivity extends AppCompatActivity {

Dialog dialog;
LinearLayout myGallery;
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_compinfo);

    dialog = new Dialog(this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(R.layout.activity_compinfopopup);
    dialog.getWindow().getAttributes().width = AbsListView.LayoutParams.MATCH_PARENT;
    dialog.getWindow().getAttributes().height = AbsListView.LayoutParams.WRAP_CONTENT;
    dialog.show();

    myGallery = (LinearLayout) dialog.findViewById(R.id.mygallery);
    myGallery.addView(insertPhoto("http://example.com/a.png"));
    myGallery.addView(insertPhoto("http://example.com/b.png"));
    myGallery.addView(insertPhoto("http://example.com/c.png"));
    myGallery.addView(insertPhoto("http://example.com/d.png"));
    new MyTask().execute();



}

View insertPhoto(String path){
    Bitmap bm;
    bm =  getBitmapFromURL(path);
    LinearLayout layout = new LinearLayout(getApplicationContext());
    layout.setLayoutParams(new AbsListView.LayoutParams(250, 250));
    layout.setGravity(Gravity.CENTER);

    ImageView imageView = new ImageView(getApplicationContext());
    imageView.setLayoutParams(new AbsListView.LayoutParams(220, 220));
    imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
    imageView.setImageBitmap(bm);

    layout.addView(imageView);
    return layout;
}


public static 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;
    }
}

2
你应该在后台线程中定义你的获取位图代码,或者使用异步任务。 - justDroid
7个回答

8

只需按照以下步骤操作 -

public class MyAsync extends AsyncTask<Void, Void, Bitmap>{

    @Override
    protected Bitmap doInBackground(Void... params) {

        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;
        }

    }
}

现在要从URL访问位图,请按以下步骤进行 -
MyAsync obj = new MyAsync(){

        @Override
        protected void onPostExecute(Bitmap bmp) {
            super.onPostExecute(bmp);

            Bitmap bm = bmp;
            LinearLayout layout = new LinearLayout(getApplicationContext());
            layout.setLayoutParams(new AbsListView.LayoutParams(250, 250));
            layout.setGravity(Gravity.CENTER);

            ImageView imageView = new ImageView(getApplicationContext());
            imageView.setLayoutParams(new AbsListView.LayoutParams(220, 220));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setImageBitmap(bm);

            layout.addView(imageView);
        }
    };

最后,执行异步任务 -

obj.execute();

@Ashish: 很高兴能帮到你 :) 请点赞支持。 - kevz

2
在Android中调用此方法将URL转换为位图。
public static Bitmap getBitmapFromURL(String url) {
        try {
            URL url = new URL(url);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setDoInput(true);
            connection.connect();
            InputStream input = connection.getInputStream();
            Bitmap bitmapFrmUrl = BitmapFactory.decodeStream(input);
            return bitmapFrmUrl;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

请不要忘记在AndroidManifest.xml中添加INTERNET权限。

1
尝试这个。
URL url = new URL("http://....");
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream()); 

只需替换您的网址,对我有效。

android.os.NetworkOnMainThreadException - Ramesh Bhati

1

正如 ankit 所说,您不应在主线程中进行任何网络调用。您将所有内容都写在了 OnCreate() 方法中。请使用 AsyncTask

我建议您使用 volley NetworkImageViewUniversal Image loader 直接从服务器上显示图像。

来自服务器的图片。


0

在UI主线程上不能进行任何网络调用。请按照以下方式实现AsyncTask并调用

new LoadImage(imageView).execute()

异步任务的实现:

class LoadImage extends AsyncTask<Object, Void, Bitmap>{

    private ImageView imv;
    private String path;

    public LoadImage(ImageView imv) {
         this.imv = imv;
         this.path = imv.getTag().toString();
    }

@Override
protected Bitmap doInBackground(Object... params) {
    Bitmap bitmap = null;
    File file = new File( 
            Environment.getExternalStorageDirectory().getAbsolutePath() + path);

    if(file.exists()){
        bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
    }

    return bitmap;
}
@Override
protected void onPostExecute(Bitmap result) {
    if (!imv.getTag().toString().equals(path)) {
           /* The path is not same. This means that this
              image view is handled by some other async task. 
              We don't do anything and return. */
           return;
    }

    if(result != null && imv != null){
        imv.setVisibility(View.VISIBLE);
        imv.setImageBitmap(result);
    }
}

}


0

将你的insertPhoto(String path)方法更改为以下内容:

View insertPhoto(String path){   
LinearLayout layout = new LinearLayout(getApplicationContext());
layout.setLayoutParams(new AbsListView.LayoutParams(250, 250));
layout.setGravity(Gravity.CENTER);

ImageView imageView = new ImageView(getApplicationContext());
imageView.setLayoutParams(new AbsListView.LayoutParams(220, 220));
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);    

  //Download and display image
        new AsyncTask<String, Void, Bitmap>(){


            @Override
            protected Bitmap doInBackground(String... urls) {
                 String url = urls[0];

                Bitmap mIcon11 = null;
                try {


                   HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                   connection.setDoInput(true);
                   connection.connect();
                   InputStream input = connection.getInputStream();
                   mIcon11 = BitmapFactory.decodeStream(input);



                } catch (Exception e) {
                    Log.e("Error for image ", e.getMessage());
                    e.printStackTrace();
                    mIcon11 = null;
                }
                return mIcon11;
            }


            protected void onPostExecute(Bitmap result) {
                if(result!= null){
                    imageView.setImageBitmap(null);
                    imageView.setImageBitmap(result);                       

                }

            }
        }.execute(path);

layout.addView(imageView);
return layout;

}

希望这能有所帮助。

0

在应用程序中显示图片,需要先将它们下载到存储中,然后再进行展示。

您可以通过搜索如何下载文件、编写OnDownloadCompleteListener来获得答案

并且每次下载完一张图片后重新加载imageView。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接