在 NetworkOnMainThreadException 中将 url 转换为位图 [重复]

Posted

技术标签:

【中文标题】在 NetworkOnMainThreadException 中将 url 转换为位图 [重复]【英文标题】:Convert url to bitmap in NetworkOnMainThreadException [duplicate] 【发布时间】:2016-05-19 00:39:22 【问题描述】:

我想将来自某些 URLS 的图像动态添加到线性布局中。运行这段代码时出现错误无法启动活动

ComponentInfo: android.os.NetworkOnMainThreadException 在 com.example.star.example.CompinfoActivity.getBitmapFromURL(CompinfoActivity.java:70) 在 com.example.star.example.CompinfoActivity.insertPhoto(CompinfoActivity.java:50) 在 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;
    

【问题讨论】:

你应该在 bcakground 线程中定义你的获取位图代码或使用异步任务 【参考方案1】:

只需执行以下操作 -

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

然后最后执行 AsynTask -

obj.execute();

【讨论】:

@Ashish:很高兴它对你有所帮助 :) 请点赞。【参考方案2】:

在android中调用此方法将Url转换为Bitmap

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 权限

【讨论】:

【参考方案3】:

试试这个

URL url = new URL("http://....");
Bitmap image = BitmapFactory.decodeStream(url.openConnection().getInputStream()); 

只需替换您的网址即可为我工作

【讨论】:

android.os.NetworkOnMainThreadException【参考方案4】:

您不应该像 ankit 所说的那样在主线程中进行任何网络调用。您在 OnCreate() 方法中编写了所有内容。请改用AsyncTask。

我建议你使用凌空NetworkImageView 或Universal Image loader。

直接从服务器显示图像。

【讨论】:

【参考方案5】:

您不能在 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);
    

【讨论】:

【参考方案6】:

在应用程序中显示图片,将它们下载到存储中,然后显示它们的作品

您将通过搜索如何下载文件、编写 OnDownloadCompleteListener 来得到答案

并在每次下载图片时重新加载您的 imageView。

【讨论】:

【参考方案7】:

更改您的 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;

希望这会有所帮助。

【讨论】:

以上是关于在 NetworkOnMainThreadException 中将 url 转换为位图 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

秋的潇洒在啥?在啥在啥?

上传的数据在云端的怎么查看,保存在啥位置?

在 React 应用程序中在哪里转换数据 - 在 Express 中还是在前端使用 React?

存储在 plist 中的数据在模拟器中有效,但在设备中无效

如何在保存在 Mongoose (ExpressJS) 之前在模型中格式化数据

如何在保存在 Mongoose (ExpressJS) 之前在模型中格式化数据