安卓学习第二弹关于网络请求那点事
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(); } }); }
相关文章推荐
- The import javax.servlet.http.HttpServletRequest cannot be resolved
- 手写服务器httpserver_封装分发器_多请求处理_多态_反射JAVA202-204
- 多达 95% 的 HTTPS 链接能被黑客劫持
- 网络基本功(1)--网络传输
- Android Http简单使用实现登录校园网App
- 多播(组播)
- 多播 、IP_ADD_MEMBERSHIP 、IP_MULTICAST_IF
- Java获取网络时间
- Linux C 网络编程——多线程的聊天室实现(服务器端)
- 最简单的基于Flash的流媒体示例:网页播放器(HTTP,RTMP,HLS)
- HTTP学习笔记:HTTP报文
- HTTP学习笔记:URL与资源
- HTTP权威指南学习笔记:连接管理
- Linux网络基础命令
- [疯狂Java]网络:GET/POST请求、设置请求属性、获取响应属性
- 3.19Java基础知识:Socket编程全部,TCPIP
- RHCE7 搭建SAMBA服务实现目录网络共享
- Android网络编程之解析XML格式数据
- [TCPIP]代理arp
- 特殊的HttpApplication事件处理