Android-通过制作HttpUtil工具类来便于进行Http通信

2023-05-16

个人是在看郭神的第一行代码时知道的可以自己做一个HttpUtil类来方便Http的通信,只需要直接用工具类里的方法进行获得Response即可了。

这里写出我自己在制作HttpUtil类时用到的不同的方法(布局的话都是一个EditText,一个按钮一个文本框,没什么特别的就不贴出来了),本文偏向于使用AsyncTask进行异步调用,先放一下效果吧。

这里也因为速度太快了ProgressBar几乎看不到了...以下就是做法了。

1.HttpURLConnection+接口回调(书上的做法,也就是我这里写的第一种方法,用接口回调的方法进行Ui的变换):

HttpCallBackListener接口:

public interface HttpCallBackListener{
    void onFinish(String response);
    void onError(Exception e);
}

HttpUtil.java工具类:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

class HttpUtil {

    static void sendHttpRequest(final String address, final HttpCallBackListener listener){
        new Thread(new Runnable() {
            @Override
            public void run() {
                HttpURLConnection conn = null;
                BufferedReader br = null;
                try {
                    URL url = new URL(address);
                    conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(8000);
                    conn.setReadTimeout(8000);
                    InputStream in = conn.getInputStream();
                    br = new BufferedReader(new InputStreamReader(in));
                    String line;
                    StringBuffer response = new StringBuffer();
                    while((line = br.readLine())!=null){
                        response.append(line);
                    }
                    if(listener != null){
                        listener.onFinish(response.toString());
                    }
                } catch (Exception e) {
                    if(listener != null){
                        listener.onError(e);
                    }
                }finally {
                    if (br != null) {
                        try {
                            br.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    if (conn != null) {
                        conn.disconnect();
                    }
                }

            }
        }).start();
    }
}

MainActivity.java:

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    EditText et_request;
    Button btn_request;
    TextView tv_response;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //各控件的初始化
        init();
    }

    private void init() {
        et_request = findViewById(R.id.et_request);
        btn_request = findViewById(R.id.btn_request);
        tv_response = findViewById(R.id.tv_response);
        btn_request.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_request :
                sendRequest();
        }
    }

    private void sendRequest() {
        HttpUtil.sendHttpRequest(et_request.getText().toString(), new HttpCallBackListener() {
            @Override
            public void onFinish(String response) {
                tv_response.setText(response);
            }

            @Override
            public void onError(Exception e) {
                Log.e("onError: ", e.toString());
            }
        });
    }

}

虽然郭神书上就是用的这个方法,但是这个方法会抛出错误异常:

在真机测试时也会卡住好一会儿,很简单也很直白的提示了,跳过了96帧,有可能在主线程做了较为耗时的操作,但是这些操作又不至于到使程序达到ANR的地步。

这是实际上仍然在主线程中进行了耗时工作,可能是因为百度主页的内容太多了,但是更重要的是这种耗时操作不应该放置到主线程中进行,所以我也用runOnUiThread的方式对sendRequest()做了一点点修改:

private void sendRequest() {
        HttpUtil.sendHttpRequest(et_request.getText().toString(), new HttpCallBackListener() {
            @Override
            public void onFinish(final String response) {
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        tv_response.setText(response);
                    }
                });

            }

            @Override
            public void onError(Exception e) {
                Log.e("onError: ", e.toString());
            }
        });
    }

实际上就是把操作放进了runOnUiThread方法里,让他在Ui线程中进行耗时操作,这样就避免了ANR错误的风险,也不会报错。这种接口回调的方法其实还是用Handler或者别的来处理比较好啊,不过用AsyncTask的话就基本不用接口回调这么麻烦了。

2.HttpURLConnection+AsyncTask的方式

HttpUtil:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

class HttpUtil {
    static String sendHttpRequest(String address){
        HttpURLConnection conn = null;
        BufferedReader br = null;
        StringBuffer response = null;
        try {
            URL url = new URL(address);
            conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(8000);
            conn.setReadTimeout(8000);
            InputStream in = conn.getInputStream();
            br = new BufferedReader(new InputStreamReader(in));
            String line;
            response = new StringBuffer();
            while((line = br.readLine())!=null){
                response.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (conn != null) {
                conn.disconnect();
            }
        }
        return response.toString();
    }


}

 

MainActivity:

 

import android.os.AsyncTask;  
import android.support.v7.app.AppCompatActivity;  
import android.os.Bundle;  
import android.view.View;  
import android.widget.Button;  
import android.widget.EditText;  
import android.widget.ProgressBar;  
import android.widget.TextView;  
  
public class MainActivity extends AppCompatActivity implements View.OnClickListener {  
  
    EditText et_request;  
    Button btn_request;  
    TextView tv_response;  
    ProgressBar pb_request;  
    //自定义的AsyncTask类  
    class MyAsyncTask extends AsyncTask<Void, Void, String>{  
       
        @Override  
        protected void onPreExecute() {  
            //在进行http访问前给进度条可视化  
            pb_request.setVisibility(View.VISIBLE);  
        }  
  
        @Override  
        protected String doInBackground(Void... voids) {  
            return HttpUtil.sendHttpRequest(et_request.getText().toString());  
        }  
  
        @Override  
        protected void onPostExecute(String s) {  
            //获得response后先隐藏进度条再在Textview中显示response信息  
            pb_request.setVisibility(View.GONE);  
            tv_response.setText(s);  
  
        }  
    }  
        @Override  
        protected void onCreate(Bundle savedInstanceState) {  
          super.onCreate(savedInstanceState);  
          setContentView(R.layout.activity_main);  
          //各控件的初始化  
          init();  
     }   
        private void init() {   
             et_request = findViewById(R.id.et_request);  
             btn_request = findViewById(R.id.btn_request);   
             tv_response = findViewById(R.id.tv_response);  
             pb_request = findViewById(R.id.pb_request);   
             btn_request.setOnClickListener(this);  
}  
        @Override   
        public void onClick(View v) {   
            switch (v.getId()){  
            case R.id.btn_request :   
                new MyAsyncTask().execute();   
        }  
     }  
}  

 

有了AsyncTask的包装后,所有的耗时操作只要在doInBackground做就完事了!虽然还是要在Main活动中创建AsyncTask类来进行,但其实操作起来还是蛮简单的,而且还有可以便于做进度条显示隐藏,十分的人性化。

 

 

按道理来说既然AsyncTask可以的话Handler也可以这样做的,不过没试过也暂时不太想尝试因为AsyncTask包装起来用着就很舒服...

 

以上两种都是用HttpURLConnection来进行Http访问的,如果把他们换成Okhttp的话说不定会更加方便,但是郭神书上用Okhttp实际上也是用的okhttp中自带的callback来进行接口回调,在回调中依然是不能进行UI更改操作的,于是我沿用第二种方法稍微改变用okhttp进行通信,便得到更方便的用法:

3.AsyncTask+Okhttp的方式

首先要记得在APP声明依赖:

implementation 'com.squareup.okhttp3:okhttp:3.10.0'

OkHttpUtil:

import java.io.IOException;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

public class OkHttpUtil {
    public static String sendOkHttpRequest(String address){
        OkHttpClient client = new OkHttpClient();
        Request request = new Request.Builder().url(address).build();
        try {
            Response response = client.newCall(request).execute();
            String data = response.body().string();
            return data;
        } catch (IOException e) {
            return e.toString();
        }
    }
}

MainActivity:

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    EditText et_request;
    Button btn_request;
    TextView tv_response;
    ProgressBar pb_request;

    class MyAsyncTask extends AsyncTask<Void, Void, String> {
        @Override
        protected void onPreExecute() {
            pb_request.setVisibility(View.VISIBLE);
        }

        @Override
        protected String doInBackground(Void... voids) {
            return OkHttpUtil.sendOkHttpRequest(et_request.getText().toString());
        }

        @Override
        protected void onPostExecute(String s) {
            pb_request.setVisibility(View.GONE);
            tv_response.setText(s);
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //各控件的初始化
        init();
    }

    private void init() {
        et_request = findViewById(R.id.et_request);
        btn_request = findViewById(R.id.btn_request);
        tv_response = findViewById(R.id.tv_response);
        pb_request = findViewById(R.id.pb_request);
        btn_request.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.btn_request :
                new MyAsyncTask().execute();
        }
    }
}

 

这样既能方便快捷的进行http访问取回数据又能方便的进行Ui操作啦。我个人是比较偏向用这种方法的。

 

本文偏向于使用AsyncTask进行异步调用因为是真的太方便了,实际上

1) 自开线程new Thread;2) runOnUIThread; 3) post方法

都是可以解决问题的,只是在这里就不详细的写了。

第一次写博客,有错误或者不足之处希望能提出来,请多多指教啦。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android-通过制作HttpUtil工具类来便于进行Http通信 的相关文章

随机推荐