学习Android过程中遇到的问题及解决方法——网络请求
在学习Android的网络连接时遇到崩溃或异常(出现的问题就这两个,但是不稳定)的问题,先上代码,看看哪里错了(答案在文末)
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"> <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"> <EditText
android:id="@+id/et_path"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="请输入网址"
android:text="https://www.baidu.com/" /> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="click"
android:text="查看" /> <ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"> <TextView
android:id="@+id/tv_result"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</ScrollView> </LinearLayout> </android.support.constraint.ConstraintLayout>
MainActivity.xml:
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL; public class MainActivity extends AppCompatActivity { private EditText et_path;
private TextView tv_result; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); et_path = findViewById(R.id.et_path);
tv_result = findViewById(R.id.tv_result); } //点检就进行查看指定路径的源码
public void click(View view) { try {
//获取源码路径
String path = et_path.getText().toString().trim();
//创建url对象制定我们要访问的路径
URL url = new URL(path);
//拿到httpUrlConnection对象
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
//设置请求方法
httpURLConnection.setRequestMethod("GET");//GET要求大写,默认get请求
//设置请求时间
httpURLConnection.setConnectTimeout(5000);
//获取服务器返回的状态码
int code = httpURLConnection.getResponseCode();
//如果code = 200,说明请求成功
if (code == 200) {
//获取服务器返回的数据,是以流的形式返回的
InputStream in = httpURLConnection.getInputStream();
System.out.println(); //将流转换成字符串
String content = StreamTools.readStreamToString(in); //展示到指定控件中
tv_result.setText(content); }
} catch (ProtocolException e) {
e.printStackTrace();
System.out.println("异常1");
} catch (MalformedURLException e) {
e.printStackTrace();
System.out.println("异常2");
} catch (IOException e) {
e.printStackTrace();
System.out.println("异常3");
} }
}
新建一个工具类来将Stream流转换成String
SrreamTools.java:
import android.content.Context; import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream; public class StreamTools {
//把inStream转换成String
public static String readStreamToString(InputStream in) throws IOException {
//定义一个内存输出流
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;
}
}
加权限
<?xml version="1.0" encoding="utf-8"?>
<manifest ……> <uses-permission android:name="android.permission.INTERNET"/> <application>
……
</application> </manifest>
以上就是出现错误的全部代码。虽然在有一些情况下会运行成功,但不久你就会发现,会崩的或者是出现异常3(不要学我写System.out.println("异常3"),要用Log,这里边与小白参考)。
上网查询问题,通过课本查询,都没有发现解决方法。网上有很多人问,有人说要在新的线程中写,有人说权限(其实一般不会发生这种低级问题),感觉回答的也是一些小白。很多并没有参考性。其中回答线程的应该是有些功底的了,下面我就发一下解决方法。
因为在4.0之后谷歌强制要求连接网络不能在主线程进行访问,所以以上的代码时不能上网的,即使加了权限也不行。此时我们为您将联网的逻辑写在新的线程中。
获取了网络信息后需要将信息展示在控件上(比如TextView),此时遇到了新的问题:更新UI异常。
这是因为更新UI必须在主线程中进行,所以引入新的API——Handler,重写Handler.handlerMessage()方法来进行更新UI;来要注意一个细节,Toast也是一个View,所以也不能在子线程中运行,也需要放在handlerMessage()中。
又有问题了:如何将在子线程要进行的逻辑在handlerMessage()中进行呢?也就是说主线程和子线程需要一个联系,不然怎么更新UI。所以新建Message对象,用Handler的sendMessage()向主线程发送Message对象,在主线程中接收,这样zhuxiancheng 就可以根据子线程发来的信息来进行应做的逻辑了。
说了这么多,不知同没听懂,还是代码实在
只需要修改MainActivity.java:
package com.lgqchinese.httphaha; import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast; import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL; public class MainActivity extends AppCompatActivity { private EditText et_path;
private TextView tv_result;
private static final int REQUESTSUEECSS = 0;
private static final int REQUESTNOTFOUNT = 1; //在主线程中定义Handler
private Handler handler = new Handler() {
//重写方法 @Override
public void handleMessage(Message msg) { //区分发来的消息时哪一条
switch (msg.what){
case REQUESTSUEECSS://代表请求成功
String content = (String) msg.obj;
tv_result.setText(content);
break;
case REQUESTNOTFOUNT://请求失败
Toast.makeText(getApplicationContext(), "请求资源不存在", Toast.LENGTH_SHORT).show();
break; } }
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); et_path = findViewById(R.id.et_path);
tv_result = findViewById(R.id.tv_result); //打印当前线程的名字
System.out.println("当前线程的名字" + Thread.currentThread().getName()); } //点检就进行查看指定路径的源码
public void click(View view) { //创建一个子线程
new Thread() {
@Override
public void run() {
try {
//获取源码路径
String path = et_path.getText().toString().trim();
//创建url对象制定我们要访问的路径
URL url = new URL(path);
//拿到httpUrlConnection对象
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
//设置请求方法
httpURLConnection.setRequestMethod("GET");//GET要求大写,默认get请求
//设置请求时间
httpURLConnection.setConnectTimeout(5000);
//获取服务器返回的状态码
int code = httpURLConnection.getResponseCode();
//如果code = 200,说明请求成功
if (code == 200) {
//获取服务器返回的数据,是以流的形式返回的
InputStream in = httpURLConnection.getInputStream();
System.out.println(); //将流转换成字符串
String content = StreamTools.readStreamToString(in); //创建Message对象
Message msg = new Message();
msg.what = REQUESTSUEECSS;
msg.obj = content;
//用创建的Handler(助手)告诉系统要更新UI
handler.sendMessage(msg); //展示到指定控件中
// tv_result.setText(content); } else {
//请求资源不存在,Toast是一个view,也不能再子线程更新UI
Message msg = new Message();
msg.what = REQUESTNOTFOUNT;
handler.sendMessage(msg);
// Toast.makeText(getApplicationContext(), "请求资源不存在", Toast.LENGTH_SHORT).show();
} } catch (ProtocolException e) {
e.printStackTrace();
System.out.println("异常1");
} catch (MalformedURLException e) {
e.printStackTrace();
System.out.println("异常2");
} catch (IOException e) {
e.printStackTrace();
System.out.println("异常3");
}
}
}.start(); }
}
可以在异常处再向主线程发信息,来提示用户加载失败,这里不再赘述,自练即可。
以上就是今天遇到的问题,个人感觉就是
因为在4.0之后谷歌强制要求连接网络不能在主线程进行访问。
学习Android过程中遇到的问题及解决方法——网络请求的更多相关文章
- 学习Android过程中遇到的问题及解决方法——电话监听
也许有时你会有这样一个需求:通电话时有一个重要的事需要记下来或者和一个陌生人特别是大骗子通话时,这是就想如果能把通话录下来就方便多了.(这才是我写这个代码的目的!!!) 在此过程中,犯了一个很大的错误 ...
- 学习Android过程中遇到的问题及解决方法——AS为xutils添加依赖
在使用xutils时遇到不能添加以来的问题,花了很长时间终于解决,网上添加依赖的方法很多,在此针对个人出现的问题作下笔记. 我本想使用jar包,因为在使用smartImageView时是用的jar包来 ...
- 国内不fq安装K8S四: 安装过程中遇到的问题和解决方法
目录 4 安装过程中遇到的问题和解决方法 4.1 常见问题 4.2 常用的操作命令 4.3 比较好的博客 国内不fq安装K8S一: 安装docker 国内不fq安装K8S二: 安装kubernet 国 ...
- 将html代码部署到阿里云服务器,并进行域名解析,以及在部署过程中遇到的问题和解决方法
本博客主要是说一下,,如何将html代码部署到阿里云服务器,并进行域名解析,以及在部署过程中遇到的问题和解决方法. 1.先在阿里云上购买一台阿里云服务器(ECS云服务器): 2.远程连接上该服务器,在 ...
- 学习Android过程中的一些博客或工具收集
android studio中使用SlidingMenu: 超简单Android Studio导入第三方库(SlidingMenu)教程绝对傻瓜版 android 更新sdk23以后,报错提示Floa ...
- 学习Android过程中遇到的未解决问题(个人笔记,细节补充,随时更新)
201811/13 使用HttpURLConnection对象调用方法又出现IO异常,我又百度个博客搜寻答案,未果.下午试试真机,完美.自己建了服务器tomcat,编写android访问自己tomca ...
- 蘑菇街TeamTalk编译连接过程中遇到的问题及解决方法(iOS)
今天浏览博文的时候,“蘑菇街开源的即时通讯框架,包括iOS.Android.Mac.Windows客户端和后台 Github源码下载地址:https://github.com/mogujie/Team ...
- 2016最新cocoapods安装流程,安装过程中遇到的问题及解决方法
现在的cocoapods与之前比较.有很多不一样的地方.自己试了一试,终于搞定.现在大概纪录一下. 1.首先查看ruby是否是最新版的. ruby是通过rvm安装的所以需要先安装rvm后查看ruby是 ...
- caffe安装过程中遇到的问题以及解决方法
1. 在安装依赖库的时候,遇到: @gxjun-Latitude-E5440:~$ sudo apt-get install libatlas-base-dev 正在读取软件包列表... 完成 正在分 ...
随机推荐
- unixbench 物理机性能与虚拟机性能测试对比
1. 测试方法 wget https://download.laobuluo.com/tools/UnixBench5.1.3.tgz tar -zxvf UnixBench5.1.3.tgz cd ...
- Ubuntu: 软件库(software repositories)
Linux 生态下,几乎每个发行版都有自己的软件库(software repositories),Ubuntu 当然也不例外.Ubuntu 提供了四个不同的软件库,分别是 main.restricte ...
- H5 36-背景定位属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 2017湘潭大学邀请赛G题(贪心+优先队列)
参考博客:http://www.cnblogs.com/chendl111/p/6891770.html 题目链接:https://www.icpc.camp/contests/4mYguiUR8k0 ...
- poj3984 广度搜索BFS
迷宫问题 Description 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1 ...
- SOAP UI-----测webservice接口
webservice的请求报文和返回报文都是xml格式的. 使用soapui.storm对webservice接口进行测试,postman无法测. http://www.webxml.com.cn/W ...
- 【问题解决方案】Git bash进入多层子目录问题(通配符问题留坑)
cd进入指定路径下:cd 斜杠 斜杠 方法一: 1- 撇丿,不是"那",盘符前面要加上 / (d盘前面也加,不加也行) 2- 路径名不区分大小写 3- 不用空格 4- 如果目录名中 ...
- MySQL 高可用性—keepalived+mysql双主
MySQL 高可用性—keepalived+mysql双主(有详细步骤和全部配置项解释) - 我的博客 - CSDN博客https://blog.csdn.net/qq_36276335/articl ...
- jenkins 迁移后 提示 反向代理设置有误
jenkins报:反向代理设置有误-布布扣-bubuko.comhttp://www.bubuko.com/infodetail-2038758.html [Linux][Jenkins]系统配置报反 ...
- Python3练习题 026:求100以内的素数
p = [i for i in range(2,100)] #建立2-99的列表 for i in range(3,100): #1和2都不用判断,从3开始 for j in range(2, ...