1.网页源码查看器
代码实现步骤
[1]搭建UI
[2]httpurlconnection类基本用法
public void click(View view) {
try {
//1.获取用户输入的路径
String path = et_path.getText().toString().trim();
//2.访问这个路径
URL url = new URL(path);
//3.通过url对象获取httpurlconnection实例 该实例用于发送或者接收数据
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4.设置一下联网超时时间
conn.setConnectTimeout(5000);
//5.设置一下请求的方式
conn.setRequestMethod("GET"); //默认是get请求
//6.获取服务器返回状态码
int code = conn.getResponseCode();
//7.对code做判断
if (code == 200){
//8.获取服务器返回的数据
InputStream is = conn.getInputStream();
//9.把流的数据读取出来 展示到textview上 由于把is转换为String是一个非常常见的操作 所以我们可以做一个工具类.
String content = StreamUtils.readStream(is);
//10.展示数据
tv_content.setText(content);
}
} catch (Exception e) {
e.printStackTrace();
}
}
[3]把流转换为String工具类
public class StreamUtils {
public static String readStream(InputStream is) throws Exception{
//1.创建内存输出流
ByteArrayOutputStream baso = new ByteArrayOutputStream();
int len = 0;
byte[] buf = new byte[1024];
while((len = is.read(buf))!=-1){
baso.write(buf,0,len);
}
//2.关流
is.close();
//baso 关闭此流无效
return baso.toString();
}
}
[4]联网要加上联网权限
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
当加上权限后 也会报如下错误
android.os.NetworkOnMainThreadException 主线程(UI线程)访问网络的异常. 主线程这个概念是谷歌提出的.
为什么会报这个异常.谷歌要求 在主线程不能进行耗时(拷贝数据 连接网络)的操作,如果在主线程中进行耗时操作会报anr(应用无响应)异常; 如何解决?我们可以自己创建一个线程 来访问网络.
[5]当我们把访问访问的操作放到子线程又会报如下错误:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
只有主线程(UI线程)才可以更新UI
[6].handler(助手)的使用 ---->负责线程的切换
6.1创建handler对象
private Handler handler = new Handler(){
//处理消息
@Override
public void handleMessage(Message msg) {
//1.先获取消息携带的数据 数据是怎么携带的就怎么取
String content = (String) msg.obj;
//2在这个方法里面更新UI
tv_content.setText(content);
}
};
6.2 发消息
//9.1构造message对象
Message msg = new Message();
//9.2 通过msg对象携带数据
msg.obj = content;
//10.使用handler进行线程的切换
handler.sendMessage(msg); ///---->handleMessage方法就会执行 这样就从子线程切换到了主线程
7.scrollView 垂直滚动的view
<ScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Hello World!" />
</ScrollView>
注意:scrollView控件只能包裹一个孩子.如果想包裹多个在外面套一个布局.
2.handler原理
3.图片查看器
[3.1]和源码查看器区别:1 UI不一样
2 数据展示的方式不一样
3 访问路径的不一样
[3.2] runOnUIthread
runOnUiThread(new Runnable() { //这个方法如果是在ui线程调用 那么这个方法会立即执行 如果调用这个方法不是在UI线程 那么要执行的动作也会运行到Ui线程
@Override
public void run() {
//run方法里面执行逻辑 运行在主线程
Toast.makeText(MainActivity.this, "服务器忙", Toast.LENGTH_SHORT).show();
}
});
[3.3]bitmapFactory 位图工厂
final Bitmap bitmap = BitmapFactory.decodeStream(is);
4.综合案例
案例设计到知识点:listview --->baseAdapter tomcat xml(xml解析) url httpurlconnection 开线程 handler
案例开发的流程
开发这样一个程序 最少3个人 一个android客户端,一个UI设计师,做服务器开发人员. 产品经理(微信).
代码实现过程:
1.画UI
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp">
<com.loopj.android.image.SmartImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:src="@mipmap/ic_launcher"
android:layout_height="wrap_content"></com.loopj.android.image.SmartImageView>
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="今日头条"
android:textSize="22sp"
android:textColor="#000000"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/iv_icon"
/>
<TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="今日头条老师老师过来过时了阿拉嘎嘎嘎"
android:textSize="17sp"
android:textColor="#999999"
android:layout_marginLeft="5dp"
android:layout_marginTop="5dp"
android:layout_toRightOf="@id/iv_icon"
android:layout_below="@id/tv_title"
/>
<TextView
android:id="@+id/tv_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="跟帖"
android:textSize="20sp"
android:textColor="#ff0000"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
/>
</RelativeLayout>
2.搭建服务器 去服务器取数据
private void initData() {
new Thread() {
@Override
public void run() {
try {
//1.定义访问的路径
String path = "http://192.168.126.62:8080/news/news.xml";
//2.访问这个路径
URL url = new URL(path);
//3.通过url对象获取httpurlconnection实例 该实例用于发送或者接收数据
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//4.设置一下联网超时时间
conn.setConnectTimeout(5000);
//5.设置一下请求的方式
conn.setRequestMethod("GET"); //默认是get请求
//6.获取服务器返回状态码
int code = conn.getResponseCode();
//7.对code做判断
if (code == 200) {
//8.获取服务器返回的数据
InputStream is = conn.getInputStream();
//9.把流的数据读取出来 解析xml 把xml解析的数据封装到list<bean>
lists = NewsXmlUtils.parserXml(is);
//10.把集合里面的数据 通过适配器展示出来
runOnUiThread(new Runnable() {
@Override
public void run() {
//11.更新适配器
lv.setAdapter(new MyAdaper());
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
3.对数据进行解析 xml解析
public static List<News> parserXml(InputStream is) {
List<News> lists=null;
News news = null;
// [1]获取解析器 xmlpullparser
XmlPullParser parser = Xml.newPullParser();
// [2]设置解析器要解析的内容
try {
parser.setInput(is, "utf-8");
// [3]获取解析器的事件类型
int eventType = parser.getEventType();
// [4]不到文件结尾就一直解析
while (eventType != XmlPullParser.END_DOCUMENT) {
// [5]具体判断一下解析到的标签 然后把我们关系的数据取出来 封装到集合中
switch (eventType) {
case XmlPullParser.START_TAG: //代表解析到的所有开始的标签
//[6]具体判断一下解析到的是哪个开始标签
if ("channel".equals(parser.getName())) {
//[7]创建一个集合对象
lists =new ArrayList<News>();
}else if ("item".equals(parser.getName())) {
//[8]创建javabean对象
news = new News();
}else if ("title".equals(parser.getName())) {
//[8.1]获取文本的数据
news.setTitle(parser.nextText());
}else if ("description".equals(parser.getName())) {
//[8.1]获取文本的数据
news.setDescription(parser.nextText());
}else if ("image".equals(parser.getName())) {
//[8.1]获取文本的数据
news.setImagepath(parser.nextText());
}else if ("type".equals(parser.getName())) {
//[8.1]获取文本的数据
news.setType(parser.nextText());
}else if ("comment".equals(parser.getName())) {
//[8.1]获取文本的数据
news.setComment(parser.nextText());
}
break;
case XmlPullParser.END_TAG: //解析到的所有的结束标签
if("item".equals(parser.getName())){
//把bean对象加入到集合中
lists.add(news);
}
break;
}
// 不停解析
eventType = parser.next();
}
//最后把集合对象返回
return lists;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
4.定义数据适配器
class MyAdaper extends BaseAdapter{
@Override
public int getCount() {
return lists.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
//获取一个view 用来展示是每个条目的内容
@Override
public View getView(int position, View convertView, ViewGroup parent) {
//1.优化
View view;
if (convertView == null){
view = View.inflate(getApplicationContext(),R.layout.item,null);
}else{
view = convertView;
}
//2.找的条目控件
TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
TextView tv_desc = (TextView) view.findViewById(R.id.tv_desc);
TextView tv_type = (TextView) view.findViewById(R.id.tv_type);
SmartImageView siv = (SmartImageView) view.findViewById(R.id.iv_icon);
//3.更新UI的数据
News news = lists.get(position);
tv_title.setText(news.getTitle()); //更新标题
tv_desc.setText(news.getDescription()); //更新标题描述
//4更新新闻类型
String typee = news.getType();
int type = Integer.parseInt(typee);
switch (type){
case 1:
tv_type.setText("国内");
break;
case 2:
tv_type.setText("娱乐");
break;
case 3:
tv_type.setText("体育");
break;
}
//5.展示图片信息
String imagepath = news.getImagepath();
siv.setImageUrl(imagepath);
return view;
}
}
5.smartImageview
5.1要先声明 要求这个类的完整包名和类名
<com.loopj.android.image.SmartImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:src="@mipmap/ic_launcher"
android:layout_height="wrap_content"></com.loopj.android.image.SmartImageView>
5.2找的控件 展示数据
//5.展示图片信息
String imagepath = news.getImagepath();
siv.setImageUrl(imagepath);