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

10min实现一个简易网站源码查看器(HttpURLConnection、ScrollView)

2016-10-10 18:03 316 查看
今天我们主要使用HttpURLConnection类(网络传输)和ScrollView(上下滚动)做一个简易的网站源码查看器。

先写一个布局文件,EditText接收输入的网站路径,Button触发操作,ScrollView(包含一个TextView)用于显示网页源码。

特别值得一提的是ScrollView只能有一个孩子,那么如果我想在ScrollView中展示多个控件(TextView、ImageView等)怎么办?

很简单,用Layout系列控件如LinearLayout,这样ScrollView只能有一个孩子LinearLayout,LinearLayout又包含多个控件(TextView、ImageView等),两全其美。

下面附上源代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.quan.car.showwebcode.MainActivity">

<EditText
android:id="@+id/path_et_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入网站路径:"
/>

<Button
android:id="@+id/show_btn_main"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示"
/>

<!--ScrollView:只能有一个孩子/使用布局文件扩展-->
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">

<TextView
android:id="@+id/content_tv_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!" />

</ScrollView>
</LinearLayout>


接下来我们学习一下HttpURLConnection类(发送和接收数据),先看最好的教材-官方文档:
http://www.android-doc.com/reference/java/net/HttpURLConnection.html
public abstract class


HttpURLConnection

extends URLConnection

An 
URLConnection
 for
HTTP (RFC 2616)
used to send and receive data over the web. Data may be of any type and length. This class may be used to send and receive streaming data whose length is not known in advance.

For
example: 

URL url = new URL("http://www.android.com/");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
try {
InputStream in = new BufferedInputStream(urlConnection.getInputStream());
readStream(in);
finally {
urlConnection.disconnect();
}
}


知行合一,下面开始实践。
1.声明控件并绑定ID:

private EditText path_et_main;
private Button show_btn_main;
private TextView content_tv_main;

path_et_main = (EditText) findViewById(R.id.path_et_main);
content_tv_main = (TextView) findViewById(R.id.content_tv_main);
show_btn_main = (Button) findViewById(R.id.show_btn_main);


2.为Button设置监听事件,我们开启一个线程以触发网络操作。
高能预警:网络请求如果在MainThread中将产生异常,

从Honeycomb SDK(3.0)开始,google不再允许网络请求(HTTP、Socket)等相关操作直接在Main Thread类中,其实本来就不应该这样做,直接在UI线程进行网络操作,会阻塞UI、用户体验相当bad!即便google不禁止,一般情况下我们也不会这么做吧。

可以参考隔壁的文章《Android之NetworkOnMainThreadException异常》。

因此我们将和network有关比较耗时的操作放到一个子线程里,然后用Handler消息机制与主线程通信。
show_btn_main.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// 开启一个子线程,进行网络操作,等待有返回结果,使用handler通知UI
Log.d(TAG, "onClick.");
new Thread(networkTask).start();
Log.d(TAG, "start.");
}
});

我们将网络操作放到子线程中,然后通过Handler发送信息。(HttpURLConnection的主要操作都在这)

Runnable networkTask = new Runnable() {

@Override
public void run() {
// TODO
// 在这里进行 http request.网络请求相关操作
String path = path_et_main.getText().toString().trim();
//https://www.baidu.com
//此方法可用于截去字符串开头和末尾的空白(如上所述)。
//shift+F2 httpWatch Record-Stop-Header、Stream
//Toast.makeText(MainActivity.this,"onClick.",Toast.LENGTH_SHORT).show();
try {
URL url = new URL(path);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");//大写,默认get
//urlConnection.setConnectTimeout(5000);
int code = urlConnection.getResponseCode();
Log.d(TAG, "code:" + code);
//Toast.makeText(MainActivity.this,"Code:" + code,Toast.LENGTH_SHORT).show();
if(code == HttpURLConnection.HTTP_OK){
InputStream in = urlConnection.getInputStream();
String content = StreamTools.readStream(in);

Message msg = new Message();
Bundle data = new Bundle();
data.putString("content", content);
Log.d(TAG, "data.putString:" + content);
msg.setData(data);
handler.sendMessage(msg);

}
} catch (Exception e) {
e.printStackTrace();
} finally {
//urlConnection.disconnect();
}

}
};


其中我们写一个小工具,将流转换为字符串。

import java.io.ByteArrayOutputStream;
import java.io.InputStream;

/**
* Created by 权兴权意 on 2016/10/10.
*/

public class StreamTools {
//将inputStream转成String
public static String readStream(InputStream in) throws Exception{
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();//内存输出流
int len = -1;
byte[] buffer = new byte[1024];//1kb
while( (len = in.read(buffer)) != -1){
byteArrayOutputStream.write(buffer,0,len);
}
in.close();
String content = new String(byteArrayOutputStream.toByteArray());
return content;
}
}


接下来在主线程中接收信息,更新UI。
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bundle data = msg.getData();
String content = data.getString("content");
Log.d(TAG, "data.getString:" + content);
//Log.i("mylog", "请求结果为-->" + val);
// TODO
// UI界面的更新等相关操作
content_tv_main.setText(content);
}
};

ok,run一下,最后效果如图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: