您的位置:首页 > 理论基础 > 计算机网络

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

2016-03-22 23:21 661 查看

网络请求显示图片

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();
}
});
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: