一般来说实现网络请求只需要使用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实现主线程数据获取)。
当然这个框架很简单,也有许多改进的地方,在网络请求代码没有根据请求码操作,读者可以自己修改(其实是我懒的改..hhhh)
还存在一些空指针的可能性,还有并发操作的优化等。
github地址:https://github.com/16115061015/GHttpData#ghttpdata