从头学android_网络图片查看器

原创 2016年05月30日 14:32:09

需求:

一个文本框,一个按钮,在文本框中输入一个图片的url,点击按钮,在按钮下方显示图像内容。

layout:

manifest:

申请使用网络的权限

    <uses-permission android:name="android.permission.INTERNET"/>

activity

        String path = editText.getText().toString();
        try {
            URL url = new URL(path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setReadTimeout(8000);
            conn.setConnectTimeout(8000);
            if (conn.getResponseCode() == 200){
                InputStream is = conn.getInputStream();
                Bitmap bitmap = BitmapFactory.decodeStream(is);
                imageView.setImageBitmap(bitmap);
            }else{
                Toast.makeText(MainActivity.this, "url错误", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

结果

API14+

但是在API 14 后的android系统中,主线程不允许访问网络,以预防网络耗时所造成的阻塞报错是

android.os.NetworkOnMainThreadException。

那么就用子线程来访问网络吧

        editText = (EditText) findViewById(R.id.et_url);
        imageView = (ImageView) findViewById(R.id.imageView);
        final String path = editText.getText().toString();
        Thread thread = new Thread(){
            @Override
            public void run() {
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setReadTimeout(8000);
                    conn.setConnectTimeout(8000);
                    if (conn.getResponseCode() == 200){
                        InputStream is = conn.getInputStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(is);
                        imageView.setImageBitmap(bitmap);
                    }else{
                        Toast.makeText(MainActivity.this, "url错误", Toast.LENGTH_SHORT).show();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        thread.start();

结果还是不行,报错Only the original thread that created a view hierarchy can touch its views

大致意思应该就是说这个view不是你这个线程创建的,你不能更改它,那么刷新UI就只能在主线程中执行了,但是网络又不能在主线程,如果两个线程直接并行的话,无法保证给ImageView设置Bitmap时,已经拿到了服务器发送的Bitmap,这怎么办呢?

android提供了messageQueue,looper 机制来解决线程间的通信问题,消息队列中存放着消息,一旦有新的消息,轮巡器就会发现,而默认情况下,轮巡器只是发现有新消息,并不做任何事情的,如果我们希望子线程已经得到了Bitmap,发送个主线程一个消息,并附带Bitmap对象,那么就要在主线程中添加一个Handler成员,并且重写它的HandleMessage方法,在这个方法中判断消息是否是子线程发过来的得到Bitmap的消息。当子线程拿到了Bitmap时,用Handler对象发送一个消息,打上标志,附加上Bitmap对象,发送出去,那么消息队列中就会有一个新消息,轮巡器就会发现它,并调用handler的handleMessage方法执行之。真是完美,不得不膜拜谷歌大神的智慧啊!

activity(API14+)

    private final static int GOTBITMAPSUCCESS = 0;
    private final static int WRONGURL = 1;
    private EditText editText;
    private ImageView imageView;

    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case GOTBITMAPSUCCESS:
                    Bitmap bm = (Bitmap) msg.obj;
                    imageView.setImageBitmap(bm);
                    break;
                case WRONGURL:
                    Toast.makeText(MainActivity.this, "url错误", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        editText = (EditText) findViewById(R.id.et_url);
        imageView = (ImageView) findViewById(R.id.imageView);
    }

    public void showImage(View v){
        final String path = editText.getText().toString();
        Thread thread = new Thread(){
            @Override
            public void run() {
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setReadTimeout(8000);
                    conn.setConnectTimeout(8000);
                    if (conn.getResponseCode() == 200){
                        InputStream is = conn.getInputStream();
                        Bitmap bitmap = BitmapFactory.decodeStream(is);

                        Message msg = new Message();
                        msg.what = GOTBITMAPSUCCESS;
                        msg.obj = bitmap;
                        handler.sendMessage(msg);
                    }else{
                        handler.sendEmptyMessage(WRONGURL);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        thread.start();
    }

总结:

1.耗时操作不能放在主线程中,网络是谷歌强制要求剥离主线程的,其他的耗时操作,如读取数据等,应该自觉遵守规范,写在其他线程中去。

2.子线程不能刷新UI,刷新UI必须要用主线程。

3.线程间的通讯可以使用MessageQueue-looper-Handler机制来实现。其中message可以携带对象传送数据。


版权声明:本文为Mr.Seng原创文章,转载注明地址:http://blog.csdn.net/mr_seng

相关文章推荐

【Android-007】【网络图片查看器】

Android学习目录项目源码下载网络图片查看器 确定图片的网址 发送http请求 URL url = new URL(address); //获取连接对象,并没有建立...

【Android基础】网络图片查看器

网络图片查看器流程从网络上获取数据: 1. 发送请求:GET 2. 接收服务器端返回的响应数据使用代码实现的步骤: 1. 创建URL,打开一个HTTP的连接; 2. 设置请求头信息...

android学习之网络图片查看器

首先,做这个小程序的时候是看的传智播客11年的

android基础--网络图片查看器

package cn.com.netimage; public class MainActivity extends Activity { private EditText imag...

android网络图片查看器

package com.itheima74.internetpicturelook; import android.graphics.Bitmap; import android.graphics....

Android--网络图片查看器

创建“网络图片浏览器”的应用程序,包名为cn.edu.bzu,项目名:picture在MainActivity中:用于是实现请求指定地址的图片,并将服务器返回的图片展示在界面上。package bzu...

[Android开发笔记]网络图片查看器的完成

初步学习了下一个网络图片查看器的写法,主要功能是用户通过EditText输入网络图片的地址,然后点击Button,在网络通畅并且地址确实存在的情况下,下方的ImageView会直接显示出该图片

Android实现网络图片查看器

Android实现从互联网上获取图片        效果图如下:    xml: <ImageView android:id="@+id/ivImage" ...

黑马Android:带缓存的网络图片查看器

android:带缓存的网络图片查看器

Android--第四天(网络图片查看器,多线程下载,文件断点上传原理,Intent,Activity生命周期,广播,服务)

网络图片查看器 json格式返回数据 多线程下载原理 进度条 文件断点上传原理
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)