网络数据请求框架的实现

       一般来说实现网络请求只需要使用HttpURLConnection实现连接读取数据流即可,但是代码太过冗余,不可能每次都手写一份,并且每次的需求有可能不同。在现有的许多优秀的开源框架如volley等的网络通信框架也有许多,自己找了些资料,手撸了一份代码简单实现了一下基本的框架。

        下面是使用的示例,只需要几行代码就可以实现对服务器端数据的读取及使用(并且得到的数据能在主线程中用于UI刷新)

 

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //自行设置一个可用的URL地址和传入的JsonMessage为JSON的JavaBean数据
        String url="";
        final TextView tv=findViewById(R.id.tv);
        GHttpData.getInstance().postTask(url, new GHttpJsonService(), new GHttpJsonListener<JsonMessage>() {
            @Override
            public void OnSuccess(JsonMessage data) {
                //data为获取到的JSON数据对应的javaBean对象
                tv.setText(data.UserInfos.get(0).toString());
            }

            @Override
            public void OnFailure() {

                tv.setText("获取数据失败!");
            }
        });

    }
}

    当然,在这个示例中我只实现了对json数据的处理,需要对其他数据的处理只需实现相应的两个接口,并在postTask中传入即可,易于对自定义的数据处理模式。

    

        按照上面的示意图我们可以逐步的剖析并实现代码

        首先是两接口的实现

GHttpService的实现:

 

 
public interface GHttpService {
    //发送请求数据
    public void PostHttpRequest(String urlstr);
    //设置监听
    public void setListener(GHttpListener gHttpListener);

}

 

GHttpListener的实现(在这里使用了泛型原因是调用者需要的数据类型不同回调的数据类型当然也不同)

 

 

public interface GHttpListener<M> {
    public void OnSuccess(M data);
    public void OnFailure();
}

框架的实现

 

package com.hzy.cnn.gethttpdata.GHttp;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**

 *线程池,负责管理异步下载线程
 */

public class GHttpData {
    private static ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    private static GHttpData gHttpData;
    private GHttpService gHttpService;
    private GHttpListener gHttpListener;
    private String url;
    public GHttpData(){

    }
    //开启线程
    public void postTask(String urlstr,GHttpService gHttpService,GHttpListener gHttpListener){
        this.gHttpService=gHttpService;
        this.gHttpListener=gHttpListener;
        this.url=urlstr;
        cachedThreadPool.execute(new Runnable() {
            @Override
            public void run() {
                GHttpData.this.gHttpService.setListener(GHttpData.this.gHttpListener);
                GHttpData.this.gHttpService.PostHttpRequest(GHttpData.this.url);
            }
        });
    }
    //单例模式
    public static GHttpData getInstance(){
        if(gHttpData==null){
            gHttpData = new GHttpData();
        }
        return gHttpData;
    }
}
 

代码中使用了单例模式是为了只存在一个线程池(这步不难理解吧)

在postTask中对两个接口进行了耦合(通过GHttpService的setListener方法;

到这里整个的框架就完成了

实际使用时只需实现自定义的接口对数据进行处理 以下是具体的实现

GHttpJsonLService的实现:

 

package com.hzy.cnn.gethttpdata.GHttp;

import android.os.Looper;
import android.util.Log;

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

/**
 * 
 */

public class GHttpJsonService implements GHttpService {
    private URL url;
    private GHttpJsonListener listener;
    private HttpURLConnection httpURLConnection;
    //获得的返回字符串
    private StringBuffer stringBuffer=new StringBuffer();

    private BufferedReader bufferedReader;

    private android.os.Handler handler=new android.os.Handler(Looper.getMainLooper());
    @Override
    public void PostHttpRequest(String urlstr) {
        //实际操作获取数据流
        try {
            String str;
            //网络请求数据
            url = new URL(urlstr);
            httpURLConnection = (HttpURLConnection) url.openConnection();
            bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
            while ((str = bufferedReader.readLine()) != null) {
                stringBuffer.append(str);
            }
            Log.i("数据", "PostHttpRequest: "+stringBuffer.toString());

            //主线程执行回调
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if(listener!=null) {
                        //回调数据
                        listener.SetData(stringBuffer);
                    }
                }
            });
        } catch (java.io.IOException e) {
            e.printStackTrace();
            //主线程执行
            handler.post(new Runnable() {
                @Override
                public void run() {
                    if(listener!=null) {
                        listener.OnFailure();
                    }
                }
            });
        }finally {
            try {
                if(bufferedReader!=null) {

                    bufferedReader.close();
                }
                if(httpURLConnection!=null){
                    httpURLConnection.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

        }

    }

    @Override
    public void setListener(GHttpListener gHttpListener) {
        this.listener =(GHttpJsonListener)gHttpListener;
    }
}

 

GHttpJsonListener的具体实现(其中如何获取泛型的类型是一个坑)

 

 

package com.hzy.cnn.gethttpdata.GHttp;
import android.util.Log;
import com.google.gson.Gson;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 */

public abstract class GHttpJsonListener<M> implements GHttpListener<M>{

    Class<M> dataclass;
    @Override
    abstract public void OnSuccess(M data);
    public void SetData(StringBuffer stringBuffer){
        //获取泛型类型
        Type genType = this.getClass().getGenericSuperclass();
        dataclass = (Class<M>)((ParameterizedType)genType).getActualTypeArguments()[0];

        Log.i("标志", "SetData: "+dataclass.getName());

        //转换为javabean数据
         Gson gson=new Gson();
         M jm = gson.fromJson(stringBuffer.toString(),dataclass);
         OnSuccess((M)jm);
    }

    @Override
    abstract public void OnFailure();
}
 

到这里对Json数据的解析也就结束了,在其中使用了Gson去解析得到的Json数据。

在GHttpService中还有一个小细节(使用Handle实现主线程数据获取)。

 

 

github地址:https://github.com/Hzy-Joel/GHttpData#ghttpdata

简介: 本框架是在Netroid的基础之上进行了封装,节省了其中配置的过程和一些不必要的操作 主要进行文本请求和图片请求,图片请求都进行了缓存(内存缓存和sd卡缓存)的封装,sd卡缓存时间可自行更改. 文本请求可传入解析的泛型clazz,即可返回解析后的clazz对象进行数据 操作,如果不需要进行数据解析,可通过另一种方式获取原生的string; 单图请求,单图请求可执行对本地asset文件夹,sd卡,http三种请求模式.只需传入相应的路径即可; 多图请求,多图请求主要是针对listview这种图文混排模式而生,能快速加载图片并实现缓存,不需要考虑 图片错位问题.只需传入相应的url即可完成全部功能. 使用说明: 1:在新创建的Manifest.xml中application中申明: <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" android:name="com.aqs.application.UApplication" > 并初始化Const.init();此处的初始化主要是对内存缓存,SD卡缓存大小,缓存时间等进行设置,如果不初始化,则按使用默认配置; 2:依赖HttpAqs-library或者jar包 3:通过公有方法进行网络请求,示例如下: >文本请求: >解析后的文本请求: HttpRequest.reqquest(int,String,Parse,Class){....}; >原生string文本请求: HttpRequest.getString(String,AqsString){...} >单张图片请求: HttpRequest.setImage(ImageView,String,int,int){...} >多张图片请求: 可使用AQSImageView控件来加载图片;特别是针对listview图文混排 实现方法: >在布局中添加 >在代码中 av.setImageUrl(url);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值