学习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 正在读取软件包列表... 完成 正在分 ...
随机推荐
- WPF仿网易云音乐系列(二、歌单创建窗口+登录设置模块)
老衲牺牲午休时间写博客,都快把自己感动了,-_-!! 之前上一篇随笔,我看了下评论,有部分人说WPF已经凉凉了,这个我觉得,这只是一个达到自己目的的工具而已,只要自己能用这个工具,得心应手的做出自己想 ...
- 内网IP外网IP的关联及访问互联网原理
首先解释一下“内网”与“外网”的概念: 内网:即所说的局域网,比如学校的局域网,局域网内每台计算机的IP地址在本局域网内具有互异性,是不可重复的.但两个局域网内的内网IP可以有相同的. 外网:即互联网 ...
- @RequestBody ajax 415 400
使用springmvc和Ajax进行数据交互时使用标签@RequestBody时我报了这两个错,刚开始对springmvc的使用和注解有点迷,然后踩坑上了. 先说下怎么才会踩上去.首先@Request ...
- Springboot+Redis 配置和使用
pom.xml 引入redis 开启缓存 <!-- cache --> <dependency> <groupId>org.springframework.boot ...
- Django之在Python中调用Django环境
Django之在Python中调用Django环境 新建一个py文件,在其中写下如下代码: import os if __name__ == '__main__': os.environ.setdef ...
- [2017BUAA软工助教]个人项目测试结果
个人项目测试结果 标签(空格分隔): 未分类 9.29第一次测试结果 注:点击表头内相应项目可针对该项目进行排序 -c测试结果 INDEX NumberID -c 1 -c 5 -c 100 -c 5 ...
- Linux之hosts文件
一.序言: 今天同事部署环境遇到问题, 原因1:修改了主机名,在/etc/hosts文件中加了3台集群的ip和主机名,但是将默认的前两行也改了,没注意看改了哪里, 现象: 1.zookeeper单台可 ...
- 学习docker——命令总结
安装docker的方法可以参考:Ubuntu.CentOS.Windows.MacOS 查看版本信息 → ~ $ docker --version Docker version 18.03.1-ce, ...
- bootStrap的使用
1.首先要打开bootstrap的官网 点进去 2你会看到下面这样一个页面里面有很多组件 这里面的代码是实现组件功能的核心代码,还不能直接使用,要引入相关的js css 我们要在起步中下载相关的页面下 ...
- Linux基础学习笔记6-SHELL编程
编程基础 程序:指令+数据 程序编程风格: 过程式:以指令为中心,数据服务于指令 对象式:以数据为中心,指令服务于数据 shell程序:提供了编程能力,解释执行 编程基本概念: 顺序执行:循环执行:选 ...