学习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 正在读取软件包列表... 完成 正在分 ...
随机推荐
- ZooKeeper: 简介, 配置及运维指南
1. 概览 ZooKeeper是一个供其它分布式应用程序使用的软件, 它为其它分布式应用程序提供所谓的协调服务. 所谓的协调服务, 是指ZooKeeper的如下能力 naming 命名 configu ...
- Log4J.xml配置详解
原文地址:https://blog.csdn.net/genyizha/article/details/74502812 Appender Appender:日志输出器,配置日志的输出级别.输出位置等 ...
- docker容器与宿主交互数据
1.查看容器 [root@localhost ~]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES cd6957191 ...
- Mysql绿色版安装和遇到的问题
MySQL绿色版安装整套流程,http://www.cnblogs.com/LiuChunfu/p/6426918.html,按这个教程装完后,用cmd命令窗口也能登陆.但是用mysql-font登不 ...
- python三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组. 注意:答案中不可以包含重复的三元组. ...
- Notepad++远程连接Linux系统
首先在官网下载 https://notepad-plus-plus.org/news/notepad-7.6.4-released.html 在命令行数输入ifconfig 查看自己的Linux的ip ...
- 【转】给word中的代码着色
基本操作 1)用Notepad++直接编辑代码文件,注意文件后缀,比如.cpp是C++程序,.m是Matlab,linux文件是.sh,写对后缀表示的文件类型,才有对应的语法高亮效果. 2)选中需要的 ...
- 2019省赛训练组队赛3.31周四-17fj
https://vjudge.net/contest/289558#overview A - Frog Therearex frogs and y chicken in a garden. Kim f ...
- 配置router列表
import Vue from "vue"; import VueRouter from 'vue-router'; import Star from '../components ...
- zTree树形菜单交互选项卡效果实现
1. 添加自定义属性 page 2. 为 ztree 每个树形节点,添加点击事件 <!DOCTYPE html> <html> <head> <meta ch ...