我的Android之旅(十)----URI 异步任务AsyncTask和get || post请求



URI:

统一资源定位符是对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.

基本URL包含模式(或称协议)、服务器名称(或IP地址)、路径和文件名,如“协议://授权/路径?查询。完整的、带有授权部分的普通统一资源标志符语法看上去如下:协议://用户名:密码@子域名.域名.顶级域名:端口号/目录/文件名.文件后缀?参数=#标志

 

模式/协议(scheme):它告诉浏览器如何处理将要打开的文件。最常用的模式是超文本传输协议(Hypertext Transfer Protocol,缩写为HTTP),这个协议可以用来访问网络。[1]  其他协议如下:

http——超文本传输协议资源

https——用安全套接字层传送的超文本传输协议

ftp——文件传输协议

mailto——电子邮件地址

ldap——轻型目录访问协议搜索

file——当地电脑或网上分享的文件

news——Usenet新闻组

gopher——Gopher协议

telnet——Telnet协议

 

protocol(协议)

指定使用的传输协议,下表列出protocol 属性的有效方案名称。 最常用的是HTTP协议,它也是目前WWW中应用最广的协议。

hostname(主机名)

是指存放资源的服务器的域名系统(DNS)主机名或 IP 地址。有时,在主机名前也可以包含连接到服务器所需的用户名和密码(格式:username:password@hostname)。

port(端口号)

整数,可选,省略时使用方案的默认端口,各种传输协议都有默认的端口号,如http的默认端口为80。如果输入时省略,则使用默认端口号。有时候出于安全或其他考虑,可以在服务器上对端口进行重定义,即采用非标准端口号,此时,URL中就不能省略端口号这一项。

path(路径)

由零或多个“/”符号隔开的字符串,一般用来表示主机上的一个目录或文件地址。

parameters(参数)

这是用于指定特殊参数的可选项。

query(查询)

可选,用于给动态网页(如使用CGIISAPIPHP/JSP/ASP/ASPNET等技术制作的网页)传递参数,可有多个参数,用“&”符号隔开,每个参数的名和值用“=”符号隔开。

fragment(信息片断)

字符串,用于指定网络资源中的片断。例如一个网页中有多个名词解释,可使用fragment直接定位到某一名词解释。

 

Android中实现异步任务机制有两种方式,HandlerAsyncTask

AsyncTask:对线程间的通讯做了包装,是后台线程和UI线程可以简易通讯:后台线程执行异步任务,将result告知UI线程。

 

一个异步任务的执行一般包括以下几个步骤:

1.execute(Params... params),执行一个异步任务,需要我们在代码中调用此方法,触发异步任务的执行。

2.onPreExecute(),在execute(Params... params)被调用后立即执行,一般用来在执行后台任务前对UI做一些标记。

3.doInBackground(Params... params),在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。

4.onProgressUpdate(Progress... values),在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。

5.onPostExecute(Result result),当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中,直接将结果显示到UI组件上。

在使用的时候,有几点需要格外注意:

 

三种泛型类型分别代表启动任务执行的输入参数后台任务执行的进度后台计算结果的类型

 Params:输入参数。对应的是调用自定义的AsyncTask的类中调用excute()方法中传递的参数。如果不需要传递参数,则直接设为Void即可Progress:子线程执行的百分比 Result:返回值类型。和doInBackground()方法的返回值类型保持一致。在使用的时候,有几点需要格外注意:

1.异步任务的实例必须在UI线程中创建。

2.execute(Params... params)方法必须在UI线程中调用。

3.不要手动调用onPreExecute()doInBackground(Params... params)onProgressUpdate(Progress... values)onPostExecute(Result result)这几个方法。

4.不能在doInBackground(Params... params)中更改UI组件的信息。

5.一个任务实例只能执行一次,如果执行第二次将会抛出异常。

    onPreExecute():无返回值类型。不传参数 doInBackground(Params... params):返回值类型和Result保持一致。参数:若无就传递Void;若有,就可用Params publishProgress(Params... params):在执行此方法的时候会直接调用onProgressUpdate(Params... values)  onProgressUpdate(Params... values)返类型。参数:若无就传递Void;若有,就可用ProgressonPostExecute(Result  result) :无返回值类型。参数:和Result保持一致。

下面便是get请求和post请求的具体实现方法了:

最重要的是理解AsyncTask异步任务

应用实例:

package com.jerehedu.jeredyuch09;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class HttpActivity extends AppCompatActivity {

    private EditText et;
    private Button search;
    private TextView show;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_http);
        et= (EditText) findViewById(R.id.et);
        search= (Button) findViewById(R.id.search);
        show= (TextView) findViewById(R.id.show);
        search.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
             String url="http://192.168.1.55:8080/HttpTest/index.jsp" +
             "?option=getUser&uName=jerehedu";
             new MyJob().execute(url);
            }
        });
    }
    /*AsyncTask异步任务类
     异步任务类的参数:
     第一个参数<String>会先传到doInBackground方法中
     第三个参数 指定doInBackground方法的返回值
              doInBackground方法的返回值会被onPostExecute方法接收
    */

    public class MyJob extends AsyncTask<String,Void,String>{

        //doInBackground在子线程中执行命令,有耗时的操作写在这里面,
        // doInBackground是必须实现的方法

        //UI线程中声明的变量,子线程内不能使用,两个方法进行转换
        @Override
        protected String doInBackground(String... strings) {
            HttpURLConnection con=null;
            InputStream is=null;
            StringBuilder sbd=new StringBuilder();

            try {
                URL url=new URL(strings[0]);
              con= (HttpURLConnection) url.openConnection();
                con.setConnectTimeout(5*1000);
                con.setReadTimeout(5*1000);
                /*
                * http响应码:getResponseCode
                  200:成功 404:未找到 500:发生错误
              */
                if (con.getResponseCode()==200){
                    is=con.getInputStream();
                    int next=0;
                    byte[] bt=new byte[1024];
                    while ((next=is.read(bt))>0){
                        sbd.append(new String(bt,0,next));
                    }
                }
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
               if (is!=null){
                   try {
                       is.close();
                   } catch (IOException e) {
                       e.printStackTrace();
                   }
               }
                if (con!=null){
                    con.disconnect();
                    //断开连接
                }
            }
            return sbd.toString();
        }
       // doInBackground执行完成后会自动进入onPostExecute方法
        //doInBackground返回的参数是onPostExecute方法的参数  S
        //onPostExecute在UI线程中执行命令
        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            show.setText(s);
            //doInBackground返回的数据
        }
    }
}

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="com.jerehedu.jeredyuch09.HttpActivity">
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/linearLayout">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="姓名"
        android:id="@+id/tv"
        android:textSize="20sp"
        />
    <EditText
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:hint="请输入要查找的姓名"
        android:id="@+id/et"
        android:textSize="20sp" />
</LinearLayout>
    <TextView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:id="@+id/show"
        android:text="查询结果"
        android:background="#e5e7a1"
        android:layout_below="@+id/search"
        android:layout_alignParentStart="true" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="查询(GET请求)"
        android:id="@+id/search"
        android:textSize="20sp"
        android:layout_below="@+id/linearLayout"
        android:layout_centerHorizontal="true" />
</RelativeLayout>


在Activity中再添加一个方法,来使用post请求方式访问网络

当然再次之前要在布局里再添加一个按钮。

 <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"
        android:text="查询post"
        android:id="@+id/search1"
        android:layout_above="@+id/show"
        android:layout_alignParentEnd="true" />


下面是post请求的方法:

注意比较二者的不同之处:有助于理解

 public class MypostJob extends AsyncTask<String,Void,String>{
        @Override
        protected String doInBackground(String... strings) {
            HttpURLConnection con=null;
            InputStream is=null;
            StringBuilder adb=new StringBuilder();
            try {
                URL url=new URL(strings[0]);
                con= (HttpURLConnection) url.openConnection();
                con.setConnectTimeout(5 * 1000);
                con.setReadTimeout(5 * 1000);
                con.setRequestMethod("POST");
                //请求方法,与GET的区别
                con.setDoInput(true);
                con.setDoOutput(true);
                con.setUseCaches(false);
                //是否存储数据
                con.setRequestProperty("Charset", "UTF-8");
                //Charset 字符集
                con.setRequestProperty("Content-type",
                        "application/x-www-form-urlencoded");
                //params应该是这样的样式=》option=getUserName&uName=jerehedu.没有问号???
                String params=strings[1];
                OutputStream os=con.getOutputStream();
                os.write(params.getBytes());
                os.flush();
                os.close();
                if (con.getResponseCode()==200){
                    is=con.getInputStream();
                    int next=0;
                   byte[] b=new byte[1024];
                    while ((next=is.read(b))>0){
                        adb.append(new String(b,0,next));
                    }

                }


            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if (is!=null){
                    try {
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (con!=null){
                    con.disconnect();
                }
            }
            return adb.toString();
        }

        @Override
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            show.setText(s);
        }
    }

点击查询按钮,即可得到下面的结果:



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值