安卓学习第二弹关于网络请求那点事

网络请求显示图片

  • 1、定义布局文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:id="@+id/lv"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/btn"
        android:text="求签"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        />

    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        />

</LinearLayout>

在main.xml中引入了上面的布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include layout="@layout/imgviewlv" />

</LinearLayout>
  • 因为是网络请求图片,所以需要加上网络权限,在AndroidManifest.xml 中加入权限
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.networdimage">

    <!--网络权限START-->
    <uses-permission android:name="android.permission.INTERNET" />
    <!--网络权限END-->
    <application android:allowBackup="true" android:label="@string/app_name"
        android:icon="@mipmap/ic_launcher" android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <activity
            android:name="com.example.administrator.networdimage.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
  • MainActivity.java
package com.example.administrator.networdimage;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by Administrator on 2016/3/23.
 */
public class MainActivity extends Activity {

    private ImageView imageView;
    //  handler消息机制,在主线程生成的全局变量,如果在子线程中声明,主线程不知道什么时候收到消息
    private Handler handler = new Handler() {
        @Override
        //处理发送过来的消息
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            //根据状态码判断,此处如果状态多的话,使用switch 应该更好,因为传过来的responseCode是int类型
            if (msg.what == 200) {
                Bitmap bitmap = (Bitmap) msg.obj;
                imageView.setImageBitmap(bitmap);
            } else if (msg.what == 404) {
                String str = (String) msg.obj;
                Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
            } else {
                String str = (String) msg.obj;
                Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
            }

        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        //找到button
        Button btn = (Button) findViewById(R.id.btn);
        //找到ImageView
        imageView = (ImageView) findViewById(R.id.img);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                /*
                * 新建一个子线程,不然会报 一个主线程的错误 叫什么NetworkMainThread 类似的
                *
                * 书写的时候,建议  new Thread().start(); 然后  new Thread(new Runnable(){...}).start();
                *
                * 因为我总是忘记在最后调用start(),导致找了很长时间的问题。
                *
                */
                //网络路径
                //若是请求本机的服务器的话,例如Tomcat,ip地址为:10.0.2.2
                final String path = "http://g.hiphotos.baidu.com/image/pic/item/0ff41bd5ad6eddc447d63bbc3edbb6fd52663347.jpg";
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            //在子线程创建一个消息实体
                            Message message = new Message();
                            //包装一个请求
                            URL url = new URL(path);
                            /**
                             * 打开一个连接
                             *
                             * 通过url.openconnection()得到一个 HttpURLConnection 注意:因为我们是Http请求,所以是HttpURLConnection
                             *
                             **/
                            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                            //生命请求的方法
                            conn.setRequestMethod("GET");
                            // 声明超时时长
                            conn.setReadTimeout(5000);
                            //得到响应的状态码
                            int responseCode = conn.getResponseCode();
                            //状态码==200代表访问正常
                            if (responseCode == 200) {
                                //获取服务器的流数据
                                InputStream is = conn.getInputStream();
                                /**
                                 * 将输入流转换为BitMap
                                 *
                                 * 通过BitmapFactroy这个工厂类里面的decodeStream(InputStream inputStream)得到ImageView所需要的BitMap
                                 *
                                 */
                                Bitmap bitmap = BitmapFactory.decodeStream(is);
                                message.what = 200;
                                message.obj = bitmap;
                            } else if (responseCode == 404) {
                                message.what = 404;
                                message.obj = "没有找到资源!";
                            } else {
                                message.obj = "请求失败了哦!";
                            }
                            //通过handle发送消息
                            handler.sendMessage(message);
                        } catch (MalformedURLException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        });
    }
}
  • 运行效果
    这里写图片描述
    这里写图片描述

  • 总结:
    在这个小工程中,遇到了一点点问题,有一个特别低级的错误。
    new Thread().start();我没有调用 start() 方法。

缓存

  • 将请求得网络图片缓存到本地,这样下一次使用直接从本地获取,在此途中遇到了几个坑。

                            InputStream inputStream = conn.getInputStream();
                            Log.i("benny", context.getCacheDir() + "");
                           (1) File file = new File(context.getCacheDir(), "cache.jpg");
                            FileOutputStream out = new FileOutputStream(file);
                            int length = -1;
                            byte[] bytes = new byte[1024];
                            while((length =inputStream.read(bytes))!=-1) {
                                out.write(bytes, 0, length);
                            }
                            inputStream.close();
                            out.close();
                           (2) Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
                            System.out.println(context.getCacheDir());

因为我没有直接在MainActivity中写而是在adapter中,所以在写获得缓存文件夹getCacheDir()的时候死获取不到,后来才发现,要 通过context.getCacheDir(),因为不能使用主线程来请求图片,只能通过子线程,所以最好是有一个线程池。会在以后的代码中加入,逐步深入嘛。


MainActivity.java

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.lv);
        //将context传到adapter中去
        listView.setAdapter(new MyAdapter(MainActivity.this));
    }

MyAdapter.java

    private Context context;
    public MyAdapter(Context context) {
        this.context = context;
    }
    //注意此处通过context来获取缓存文件夹
    File file = new File(context.getCacheDir(), "cache.jpg");
  • Adapter代码
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.Toast;

import com.example.administrator.imageviewtest.R;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

/**
 * Created by benny on 2016/3/24.
 */
public class MyAdapter extends BaseAdapter {


    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == 200) {
                imageView.setImageBitmap(BitmapFactory.decodeFile(file.getAbsolutePath()));
            }
            else Toast.makeText(context, msg.obj.toString(), Toast.LENGTH_SHORT).show();
        }
    };

    private ImageView imageView;
    private Context context;
    private File file;


    public MyAdapter(Context context) {
        this.context = context;
    }

    @Override
    public int getCount() {
        return 12;
    }

    @Override
    public Object getItem(int position) {
        return null;
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater factory = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View view = null;
        if (view == null) {
            view = factory.inflate(R.layout.item, null);
        } else {
            view = convertView;
        }
        imageView = (ImageView) view.findViewById(R.id.iv);

        file = new File(context.getCacheDir(), "cache.jpg");
        if (file.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
            imageView.setImageBitmap(bitmap);
            Toast.makeText(context, "用的是缓存哦", Toast.LENGTH_SHORT).show();
        } else {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    String path = "http://imgsrc.baidu.com/forum/w%3D580/sign=fdc0d4a0d4ca7bcb7d7bc7278e086b3f/6ae2a944ad3459823d7908f10ff431adcaef84a6.jpg";
                    Message msg = new Message();
                    URL url = null;

                    try {
                        url = new URL(path);
                        HttpURLConnection conn = null;
                        try {
                            conn = (HttpURLConnection) url.openConnection();
                            conn.setRequestMethod("GET");
                            conn.setReadTimeout(5000);

                            int responseCode = conn.getResponseCode();
                            if (responseCode == 200) {

                                InputStream inputStream = conn.getInputStream();
                                Log.i("benny", context.getCacheDir() + "");
                                File file = new File(context.getCacheDir(), "cache.jpg");
                                FileOutputStream out = new FileOutputStream(file);
                                int length = -1;
                                byte[] bytes = new byte[1024];
                                while ((length = inputStream.read(bytes)) != -1) {
                                    out.write(bytes, 0, length);
                                }
                                inputStream.close();
                                out.close();
                                msg.what = 200;
                            } else {
                                msg.obj = "啥几把万一啊";
                                msg.what = 404;
                            }
                            handler.sendMessage(msg);
                        } catch (MalformedURLException e1) {
                            e1.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
//        imageView.setImageBitmap(bitmap);
        }

        return view;
    }
}

这里写图片描述

网页源码查看器之(ScrollView)

如果是TextView的话,是不支持滑动的,所以我们需要用到ScrollView,而ScrollView中包裹的元素只能有一个,如果我们需要ScrollView包裹多个元素的话,可以在ScrollView中嵌套一个布局如:LinearLayout…

 <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content">

            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content" />
            <TextView
                android:id="@+id/txt_content"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/txt_title"
                android:layout_margin="10dp"
                android:layout_toRightOf="@+id/iv"
                android:text="ScrollView中嵌套LinearLayout" />

        </LinearLayout>

    </ScrollView>

消息处理的api

  • 消息创建的方式(1)
    • Message msg = new Message();
  • 消息创建的方式 (2)
    • Message msg = Message.obtain(handler);
  • 消息创建的方式 (3)
    • Message msg = handler.obtainMessage();

  • 消息发送的方式(1)
    • handler.sendMessage(msg);
  • 消息发送的方式 (2)
    • msg.sendToTarget();
//携带int类型参数
msg.arg1=1;
msg.arg2=2;
//消息的唯一标识
msg.what =200;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.lv);
        listView.setAdapter(new MyAdapter(MainActivity.this));

        new Thread(new Runnable() {
            @Override
            public void run() {
                //在子线程中也可以打印
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,"在子线程也可以打印哦",Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }).start();
    }
-----------------------提取一下-----------------------
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ListView listView = (ListView) findViewById(R.id.lv);
        listView.setAdapter(new MyAdapter(MainActivity.this));

        new Thread(new Runnable() {
            @Override
            public void run() {
                showToast("在子线程也可以打印toast哦");
            }
        }).start();
    }

    private void showToast(final String str) {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, str, Toast.LENGTH_SHORT).show();
            }
        });
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值