zoukankan      html  css  js  c++  java
  • Android加载网络图片报android.os.NetworkOnMainThreadException异常

    Android加载网络图片大致可以分为两种,低版本的和高版本的。低版本比如4.0一下或者更低版本的API直接利用Http就能实现了:

    1.main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
     
        <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="@string/imagepath" />
         
        <EditText
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="http://10.191.92.7:8080/web/xiaoxiao.jpg"
            android:id="@+id/imagepath"/>
         
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/button"
             
            android:id="@+id/button"/>
         
         
        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageView"/>
         
         
         
     
    </LinearLayout>

    2.MainActivity.java

    复制代码
    package ygc.yxb.image;
    
    import ygc.yxb.service.ImageService;
    import android.app.Activity;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
        private EditText pathText;
        private ImageView imageView;
        
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            //获得图片路径
            pathText=(EditText) this.findViewById(R.id.imagepath);
            //获得要显示的imageView
            imageView=(ImageView) this.findViewById(R.id.imageView);
           //获得button按钮 
           Button button=(Button) this.findViewById(R.id.button);
           
           //注册button按钮的点击事件
           button.setOnClickListener(new ButtonClickListener());
            
        }
        
        private final class ButtonClickListener implements View.OnClickListener{
    
            @Override
            public void onClick(View v) {
                String path=pathText.getText().toString();
                try {
                    //业务逻辑层:ImageService类的getImage方法用以获取网络图片
                    byte[] data = ImageService.getImage(path);
                    //用字节数组所有信息生成位图对象
                    Bitmap bitmap =BitmapFactory.decodeByteArray(data, 0, data.length);
                    imageView.setImageBitmap(bitmap);//显示图片
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(getApplicationContext(), R.string.error, 1).show();
                }
                
                
            }
            
            
        }
    }
    复制代码

    3.ImageService.java

    复制代码
    package ygc.yxb.service;
    
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    
    import ygc.yxb.utils.StreamTool;
    
    public class ImageService {
    
        /**
         * 获取网络图片的数据
         * @param path 网络图片路径
         * @return
         */
        public static byte[] getImage(String path) throws Exception {
            
            URL url = new URL(path);
            HttpURLConnection conn=(HttpURLConnection)url.openConnection();    //基于HTTP协议的连接对象
            conn.setConnectTimeout(5000);//5秒
            conn.setRequestMethod("GET");//请求方式
            //判断请求是否成功
            if(conn.getResponseCode()==200){
                //定义输入流
                InputStream inStream = conn.getInputStream();
                return StreamTool.read(inStream);
                
            }
            
            return null;
        }
    
    }
    复制代码

    4.StreamTool.java 输入流工具类。

    复制代码
    package ygc.yxb.utils;
    
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    
    public class StreamTool {
    
        /**
         * 读取流中的数据
         * @param inStream
         * @return
         * @throws Exception
         */
        public static byte[] read(InputStream inStream) throws Exception {
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            //如果字节流中的数据不等于-1,就说明一直有,然后循环读出
            while( (len=inStream.read(buffer)) !=-1){
                //将读出的数据放入内存中
                outputStream.write(buffer);
                
            }
            inStream.close();
            return outputStream.toByteArray();
        }
    
    }
    复制代码

    5.AndroidManifest.xml 在清单文件配置访问网络的权限。

     <!-- 访问internet权限 -->
       <uses-permission android:name="android.permission.INTERNET"/>

    而如果4.0或者以上版本的话就不能直接获取图片了,直接获取网络图片就会报出android.os.NetworkOnMainThreadException异常,因为4.0以上访问网络的功能不能发生在主线程中运行,而如果把上面访问方式改为异步操作就不会出现在4.0上访问报出 android.os.NetworkOnMainThreadException异常了。

     如添加一个异步类,将原来(上文)在activity的onclick中执行的事件放到这里面

    import com.hello.db.R;
    import com.hello.service.ImageService;
    
    import android.database.CursorJoiner.Result;
    import android.graphics.Bitmap;
    import android.graphics.BitmapFactory;
    import android.os.AsyncTask;
    import android.widget.ImageView;
    import android.widget.Toast;
    
    public class ImageAsync extends AsyncTask<String, Bitmap, Bitmap> {//三个参数:第一个参数表示指定doInBackGround()方法中的参数类型,第二个参数表示指定OnPostExcut                                                                   //e()方法中的参数类型,第三个参数表示doInbackGround()方法的返回值类型,必须与OnPostExcute()/                                                                   //方法的参数类型相同。(仅为个人理解,错误之处还请各位大神指出…谢啦)
        private ImageView imageView;
    
        public ImageAsync(ImageView imageView) {
            this.imageView = imageView;
        }
    
        @Override
        protected Bitmap doInBackground(String... params) {
            String ipath = params[0];
            Bitmap bitmap=null;
            try{
                
                byte[] data=ImageService.getImage(ipath);
                
                bitmap=BitmapFactory.decodeByteArray(data, 0, data.length);
                
                }
                
                catch(Exception e){
                    e.printStackTrace();
                    
                }
    
            return bitmap;
        }
    
        @Override
        protected void onPostExecute(Bitmap result) {
        // TODO Auto-generated method stub
        imageView.setImageBitmap(result);
        }
    }
  • 相关阅读:
    PHP开发经常遇到的几个错误
    PHP的Trait
    PHP反射API
    php split 和 explode 的区别
    php判断检测一个数组里有没有重复的值
    PHP serialize 和 JSON 解析与区别
    php 单文件上传
    php 数组 类对象 值传递 引用传递 区别
    六. 网络编程(解决黏包TCP)
    五. 网络编程(UDP 不黏包)
  • 原文地址:https://www.cnblogs.com/xiaoerlang90/p/4157649.html
Copyright © 2011-2022 走看看