day04 网络编程

1.写一个网络源码查看器

思路:

1.写布局 EditText Button TextView ok

2.找控件,设置点击事件 ok

3.在点击事件的onclick中,获取用户输入的url ok

4.访问url,获取源码 ********* 不ok

//4.1 创建一个URL对象;

URL url = new URL(url_str);

//4.2 通过url对象获取一个HttpUrlConnection对象

HttpURLConnection cn = (HttpURLConnection) url.openConnection();

//4.3 为HttpUrlConnection对象设置一些参数 . 如:网络请求方式 ,连接的超时时间

cn.setRequestMethod("GET");//设置网络的请求方式 GET ,POST一定 要大写

cn.setConnectTimeout(10*1000);//设置网络连接的超时时间

//4.4 获取网络的响应状态码

int code = cn.getResponseCode();//获取服务器的响应码

//4.5判断状态码是否是200,如果是200 获取流数据

if(code == 200){

InputStream inputStream = cn.getInputStream();//获取一个读取流读取服务器返回的数据

//4.6 将获取的流数据转换成字符串,就是我们所需的源码

String result = Utils.StreamToString(inputStream);

//5.将源码显示到TextView上

tv_source.setText(result);

}

5.将源码显示到TextView上

2.出现的问题

1.注意添加网络访问权限:

2.ANR: 多次点击按钮会出现application not response应用无响应的异常;

安卓规定耗时的操作(网络请求,大文件的拷贝,数据库的操作)需要放到子线程中执行,不能在主线程中执行.4.0以后android强制要求网络请求必须放到子线程中执行,android4.0之后会报错误:NetworkOnMainThreadException;

11-01 02:44:12.618: E/ActivityManager(858): ANR in com.itheima.sourcelook (com.itheima.sourcelook/.MainActivity)

3.NetworkOnMainThreadException 网络访问在主线程异常

11-01 02:47:40.231: W/System.err(1806): android.os.NetworkOnMainThreadException

4.当创建了子线程并将操作放入子线程之后会报CalledFromWrongThreadException 错误的线程调用异常 ,只有主线程才能够更新UI,子线程不能更新UI(改变控件的内容或样式)。

11-01 02:56:07.750: W/System.err(1947): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.

结论:耗时的操作需要放到子线程中执行,不能在主线程中执行;只有主线程才能更新UI,子线程获取到数据不能直接更新UI.产生了矛盾。。如何解决? Handler

3.handler消息机制

思路:

1.在主线程创建一个Handler对象,成员变量。

new Handler()

2.重新handler对象的handlerMessage方法

new Handler(){

handlerMessage(Message msg){

}

}

3.在子线程中创建一个Message对象。

Message msg = new Message();

4.将子线程获取的结果绑定给Message对象

msg.obj = result;

5.子线程中使用主线程创建的handler将Message对象发送到主线程

handler.sendMessage(msg);

6.主线程中的handler对象的handlerMessage方法接受子线程发来的Message对象,可以获取Message对象中绑定的数据,做UI更新

new Handler(){

handlerMessage(Message msg){

String result = msg.obj;

textview.setText(result);

}

}

4.网络图片查看器

BitmapFactory 可以将各种各样的资源(文件,流,二进制数组)转换成一个Bitmap对象。

Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

代码:

protectedvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//2.找控件,写点击事件

et_url = (EditText) findViewById(R.id.et_url);

img_pic = (ImageView) findViewById(R.id.img_pic);

findViewById(R.id.bt_getpic).setOnClickListener(this);

System.out.println("oncreate:"+Thread.currentThread().getName());

}

//☆☆☆☆☆  1.在主线程中创建一个Handler对象

privateHandler handler =newHandler(){

//☆☆☆☆☆  2.复写Handler对象的一个handlerMessage方法

publicvoidhandleMessage(android.os.Message msg) {

//☆☆☆☆☆  6.在主线程的handler对象中的handleMessage方法接受子线程发来的Message对象,并获取绑定的数据;那么主线程就可以更新UI了。

Bitmap bm  = (Bitmap) msg.obj;

// 当前线程为主线程,可以更新Ui

//5.将bitmap设置给Imageview做展示

img_pic.setImageBitmap(bm);

};

};

@Override

publicvoidonClick(View v) {

//创建一个子线程

newThread(newRunnable() {

@Override

publicvoidrun() {

System.out.println("runnable:"+Thread.currentThread().getName());

//3.在点击事件的onclick中,获取用户输入的url  ok

String url_str = et_url.getText().toString().trim();

try{

//4.访问url,获取源码              ********* 不ok

//4.1 创建一个URL对象;

URL url =newURL(url_str);

//4.2 通过url对象获取一个HttpUrlConnection对象

HttpURLConnection cn = (HttpURLConnection) url.openConnection();

//4.3  为HttpUrlConnection对象设置一些参数 .   如:网络请求方式 ,连接的超时时间

cn.setRequestMethod("GET");//设置网络的请求方式 GET ,POST一定 要大写

cn.setConnectTimeout(10*1000);//设置网络连接的超时时间

//4.4 获取网络的响应状态码

intcode = cn.getResponseCode();//获取服务器的响应码

//4.5判断状态码是否是200,如果是200 获取流数据

if(code == 200){

InputStream inputStream = cn.getInputStream();//获取一个读取流读取服务器返回的数据

//4.6 将获取的流数据转换成图片资源   Drawable Bitmap:位图

//使用BitmapFactory将各种资源(流,文件,二进制数组)转换成图片对象Bitmap

Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

//☆☆☆☆☆  3.在子线程中创建一个Message对象

Message msg =newMessage();

//☆☆☆☆☆  4.将子线程中获取的数据绑定给Message对象

msg.obj = bitmap;

//☆☆☆☆☆  5.使用主线程中的handler对象将绑定数据的Message对象发送到主线程

handler.sendMessage(msg);

}

}catch(Exception e) {

e.printStackTrace();

}

}

}).start();

}

5.设计自己的SmartImageView控件(可以通过URI设置控件显示的图片)

思路:

1.通过httpurlconnection连接网络资源

2.通过bitmapfactory获得bitmap(factory可以通过流转换bitmap)

3.建立message

4.用handler传递message获得bitmap

5.在自己的控件中显示

注意:

自定义控件:

1.写一个类继承ImageView,写三个构造方法

2.写一个setImageUrl方法,请求url地址,获取图片流,转换成bitmap,设置给当前类的对象。

3.在布局文件中引用自定义的MySmartImageView ,注意,引用时,需要指定类的完整路径。

代码

publicclassMySmartImageViewextendsImageView{

Handlerhand=newHandler(){

publicvoidhandleMessage(Message msg) {

Bitmap img=(Bitmap) msg.obj;

//自定义控件标签要写全包名

//

//android:layout_height="68dp"

//android:layout_width="68dp"

//android:layout_margin="10dp"

//android:id="@+id/iv_view"

//android:src="@drawable/ic_launcher"/>

MySmartImageView.this.setImageBitmap(img);

};

};

//一定要复写3个方法,否则运行会报错

publicMySmartImageView(Context context, AttributeSet attrs,intdefStyle) {

super(context, attrs, defStyle);

//TODOAuto-generated constructor stub

}

publicMySmartImageView(Context context, AttributeSet attrs) {

super(context, attrs);

//TODOAuto-generated constructor stub

}

publicMySmartImageView(Context context) {

super(context);

//TODOAuto-generated constructor stub

}

publicvoidSetImageUrl(String url)

{

finalString url2=url;

newThread(newRunnable() {

@Override

publicvoidrun() {

try{

URL url1=newURL(url2);

HttpURLConnection con=(HttpURLConnection) url1.openConnection();

con.setReadTimeout(10000);

con.setRequestMethod("GET");

if(con.getResponseCode()==200)

{

InputStream in=con.getInputStream();

Bitmap img=BitmapFactory.decodeStream(in);

Message msg=newMessage();

msg.obj=img;

hand.sendMessage(msg);

}

}catch(MalformedURLException e) {

//TODOAuto-generated catch block

e.printStackTrace();

}catch(IOException e) {

//TODOAuto-generated catch block

e.printStackTrace();

}

//TODOAuto-generated method stub

}

}).start();

}

}

6.常见消息处理API

1.子线程可以更新UI的情况

//面试:: 审计机制 ,在activity完全显示之后才会工作,才会检测是否在子线程中更新UI,显示之前更新UI审计机制不会工作。

// 还有一些情况可以在子线程更新Ui,如SurfaceView和与进度条相关的控件都可以在子线程更新UI。

代码:

@Override

protectedvoidonCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

tv_text= (TextView)findViewById(R.id.tv_text);

//SystemClock.sleep(5000);

newThread(newRunnable() {

publicvoidrun() {

SystemClock.sleep(5000);

tv_text.setText("我被更新了");

}

}).start();

}

2.runOnUiThread方法:无论当前线程是否是主线程,都会被在主线程中执行

//在activity中有一个runOnUIthread方法,UI线程就是主线程无论要运行的动作是否是主线程,都将会在主线程运行。

runOnUiThread(new Runnable() {

@Override

public void run() {

tv_simple.setText("我被更新了");

}

});

3.handler 的post方法

//使用handler 的post方法将一个动作发送到主线程去执行。 这个handler必须定义在主线程

handler.post(new Runnable() {

@Override

public void run() {

tv_simple.setText("我被更新了");

}

});

4.handler 的postDelaed方法,发送一个延迟的动作到主线程,特别适合做广告展示。

//delayMillis:延迟的时间

handler.postDelayed(new Runnable() {

@Override

public void run() {

tv_simple.setText("我被更新了");

}

}, 5000);

7.android的Json解析

1.android自带Json封装API

String result = Utils.StreamToString(inputStream);//获得一个Json字符串

//6.解析json字符串,封装到list中

JSONObject root_json = new JSONObject(result);//将一个json字符串转换成一个jsonObject

//根据json的key获取newss这个json数组

JSONArray jsonArray = root_json.getJSONArray("newss");

//遍历jsonArray获取一条条json数据

for (int i = 0; i < jsonArray.length(); i++) {

JSONObject newsJson = jsonArray.getJSONObject(i);//根据索引获取数组中的一个json对象

NewsBean bean = new NewsBean();

bean.id = newsJson.getInt("id");

bean.comment = newsJson.getInt("comment");

bean.type = newsJson.getInt("type");

bean.title =      newsJson.getString("title");

bean.des =      newsJson.getString("des");

bean.icon_url = newsJson.getString("icon_url");

bean.news_url = newsJson.getString("news_url");

bean.time = newsJson.getString("time");

arrayList.add(bean);

2.第三方工具包解析介绍(最好选择Gson)

1.、各个JSON技术的简介和优劣

1.json-lib

json-lib最开始的也是应用最广泛的json解析工具,json-lib 不好的地方确实是依赖于很多第三方包,

包括commons-beanutils.jar,commons-collections-3.2.jar,commons-lang-2.6.jar,commons-logging-1.1.1.jar,ezmorph-1.0.6.jar,

对于复杂类型的转换,json-lib对于json转换成bean还有缺陷,比如一个类里面会出现另一个类的list或者map集合,json-lib从json到bean的转换就会出现问题。

json-lib在功能和性能上面都不能满足现在互联网化的需求。

2.开源的Jackson

相比json-lib框架,Jackson所依赖的jar包较少,简单易用并且性能也要相对高些。

而且Jackson社区相对比较活跃,更新速度也比较快。

Jackson对于复杂类型的json转换bean会出现问题,一些集合Map,List的转换出现问题。

Jackson对于复杂类型的bean转换Json,转换的json格式不是标准的Json格式

3.Google的Gson

Gson是目前功能最全的Json解析神器,Gson当初是为因应Google公司内部需求而由Google自行研发而来,

但自从在2008年五月公开发布第一版后已被许多公司或用户应用。

Gson的应用主要为toJson与fromJson两个转换函数,无依赖,不需要例外额外的jar,能够直接跑在JDK上。

而在使用这种对象转换之前需先创建好对象的类型以及其成员才能成功的将JSON字符串成功转换成相对应的对象。

类里面只要有get和set方法,Gson完全可以将复杂类型的json到bean或bean到json的转换,是JSON解析的神器。

Gson在功能上面无可挑剔,但是性能上面比FastJson有所差距。

4.阿里巴巴的FastJson

Fastjson是一个Java语言编写的高性能的JSON处理器,由阿里巴巴公司开发。

无依赖,不需要例外额外的jar,能够直接跑在JDK上。

FastJson在复杂类型的Bean转换Json上会出现一些问题,可能会出现引用的类型,导致Json转换出错,需要制定引用。

FastJson采用独创的算法,将parse的速度提升到极致,超过所有json库。

综上4种Json技术的比较,在项目选型的时候可以使用Google的Gson和阿里巴巴的FastJson两种并行使用,

如果只是功能要求,没有性能要求,可以使用google的Gson,

如果有性能上面的要求可以使用Gson将bean转换json确保数据的正确,使用FastJson将Json转换Bean

Gson解析:

你可能感兴趣的:(day04 网络编程)