Android访问网络的常用方式:Handler、AsyncTask简单例子(服务器端+Android端)
来源:互联网 发布:johnston murphy 淘宝 编辑:程序博客网 时间:2024/06/01 09:20
原文地址:http://blog.csdn.net/xuejingfu1/article/details/51915033
首先应该明白两点:
1.Android不允许在主线程(对于android来说,主线程就是UI线程)中访问网络。
2.Android不允许在一个子线程中直接去更新主线程中的UI控件。
对于问题1,可能你会说,这还不好办吗?再开一个线程不就完了?是的,你很聪明,原理也很简单。
对于问题2,就需要用到线程间通信(IPC),Android很好的将其进行了封装,也就有了今天的Handler和AsyncTask。
适用情况:
AsyncTask是一个轻量级的后台异步任务类,简单、便捷。适合后台任务不太多的情况,因为每一个后台任务都要写成一个Class去继承AsyncTask,代码显得比较臃肿。否则就使用Handler吧,很强大,但对于新手来说较难掌握
使用方法:
AsyncTask定义了三种泛型类型 Params,Progress和Result。
- Params 启动任务执行的输入参数,比如HTTP请求的URL。
- Progress 后台任务执行的百分比。
- Result 后台执行任务最终返回的结果,比如String。
最少要重写以下方法:
- doInBackground(Params…) 后台执行,比较耗时的操作都可以放在这里。注意这里不能直接操作UI。此方法在后台线程执行,完成任务的主要工作,通常需要较长的时间。在执行过程中可以调用publicProgress(Progress…)来更新任务的进度。(必须重写)
- onPostExecute(Result) 相当于Handler 处理UI的方式,在这里面可以使用在doInBackground 得到的结果处理操作UI。 此方法在主线程执行,任务执行的结果作为此方法的参数返回(可以不重写,因为你可以用post(Runable r)来更新UI,但既然用了AsyncTask,直接重写这个方法多方便呢!)
有必要的话你还得重写以下这三个方法,但不是必须的:
- onProgressUpdate(Progress…) 可以使用进度条增加用户体验度。 此方法在主线程执行,用于显示任务执行的进度。
- onPreExecute() 这里是最终用户调用Excute时的接口,当任务执行之前开始调用此方法,可以在这里显示进度对话框。
- onCancelled() 用户调用取消时,要做的操作
使用AsyncTask类,以下是几条必须遵守的准则:
- Task的实例必须在UI thread中创建;
- execute方法必须在UI thread中调用;
- 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法;
- 该task只能被执行一次,否则多次调用时将会出现异常;
Handler的使用要搭配线程(Thread)。具体使用方法,请看下面小例子。
服务器端代码:生成一个0到10之间的的随机数,并封装成JSON对象
- package com.test.servlet;
-
- import java.io.IOException;
- import java.io.PrintWriter;
-
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
-
- public class TestServlet extends HttpServlet {
-
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
-
- doPost(request, response);
- }
-
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
-
- response.setContentType("text/html");
- PrintWriter out = response.getWriter();
-
- out.println("{\"rand\":"+"\""+(int)(Math.random()*10)+"\""+"}");
- out.flush();
- out.close();
- }
-
- }
这时先通过浏览器访问测试是否成功:
注意:8888是本人修改了tomcat的端口号,默认是8080哦,你们别学我^_^.
Android端:
布局文件就一个Textview用来显示数据:
- <?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:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:context="xjtu.com.test.MainActivity">
-
- <TextView
- android:id="@+id/tv"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:textSize="50sp"
- android:gravity="center"/>
- </LinearLayout>
注意在Manifest文件中加入网络访问权限:
<uses-permission android:name="android.permission.INTERNET"/>
代码:
第一种方式AsyncTask:
- package xjtu.com.test;
-
- import android.os.AsyncTask;
- import android.support.v7.app.AppCompatActivity;
- import android.os.Bundle;
- import android.widget.TextView;
-
- import org.json.JSONObject;
-
- import xjtu.com.utils.HttpUtils;
-
- public class MainActivity extends AppCompatActivity {
-
- private TextView tv;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- tv=(TextView)findViewById(R.id.tv);
- new GetData().execute();
- }
-
- class GetData extends AsyncTask<Void,Void,String>{
-
- @Override
- protected String doInBackground(Void... params) {
-
- String json_str= HttpUtils.getJsonContent(HttpUtils.BaseUrl);
- String result="";
- try{
- JSONObject js_obj=new JSONObject(json_str);
- result=js_obj.getString("rand");
- }catch (Exception e){
- e.printStackTrace();
- }
-
- return result;
- }
-
- @Override
- protected void onPostExecute(String s) {
- tv.setText(s);
- }
- }
- }
onPostExecute(String s)的参数s实际上是doInBackground方法的返回值result
结果截图:
第二种方式:Handler
- package xjtu.com.test;
-
- import android.os.Handler;
- import android.os.Message;
- import android.support.v7.app.AppCompatActivity;
- import android.os.Bundle;
- import android.widget.TextView;
-
- import org.json.JSONObject;
-
- import xjtu.com.utils.HttpUtils;
-
- public class MainActivity extends AppCompatActivity {
-
- private TextView tv;
- private Thread thread;
- private Handler handler;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
-
- tv=(TextView)findViewById(R.id.tv);
-
-
- handler=new Handler(){
- @Override
- public void handleMessage(Message msg) {
-
- if (msg.what == 0x123){
- Bundle bundle=msg.getData();
- tv.setText(bundle.getString("text"));
- }
- }
- };
- }
-
- @Override
- protected void onResume() {
- super.onResume();
- thread=new Thread(new Runnable() {
- @Override
- public void run() {
-
- while(!Thread.currentThread().isInterrupted()) {
-
- String json_str = HttpUtils.getJsonContent(HttpUtils.BaseUrl);
- String result = "";
- try {
- JSONObject js_obj = new JSONObject(json_str);
- result = js_obj.getString("rand");
-
-
- Message message = new Message();
- message.what = 0x123;
- Bundle bundle = new Bundle();
- bundle.putString("text", result);
- message.setData(bundle);
- handler.sendMessage(message);
-
- Thread.sleep(1000);
-
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- }
-
- }
- });
-
-
- thread.start();
- }
-
- @Override
- protected void onStop() {
- super.onStop();
-
- thread.interrupt();
- }
-
- }
这样得到的随机数每秒更新一次。
最后,以上代码中还用到了一个访问网络的封装类,代码如下:
- package xjtu.com.utils;
-
- import java.io.ByteArrayOutputStream;
- import java.io.InputStream;
- import java.net.HttpURLConnection;
- import java.net.URL;
-
- public class HttpUtils {
-
- public static String BaseUrl = "http://172.16.0.10:8888/Test/servlet/TestServlet";
-
- public static String getJsonContent(String path) {
- try {
- URL url = new URL(path);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setConnectTimeout(3000);
- connection.setRequestMethod("GET");
- connection.setDoInput(true);
- int code = connection.getResponseCode();
- if (code == 200) {
- return changeInputString(connection.getInputStream());
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return "";
- }
-
- private static String changeInputString(InputStream inputStream) {
-
- String jsonString = "";
- ByteArrayOutputStream outPutStream = new ByteArrayOutputStream();
- byte[] data = new byte[1024];
- int len = 0;
- try {
- while ((len = inputStream.read(data)) != -1) {
- outPutStream.write(data, 0, len);
- }
- jsonString = new String(outPutStream.toByteArray());
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return jsonString;
- }
- }
0 0