Skip to content

oeager/BsinceEvent

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

BsinceEvent

这是一个基于HttpUrlConnection的Android异步网络框架。

##特点:

  • 高度的可配置化.全局配置与单次事件配置都是可控的.
  • 支持请求的重试,重定义,代理,认证,取消等.
  • 支持自动化的Cookie管理
  • 支持http缓存.
  • 实现请求参数的封装与响应的回调.
  • 支持Http的所有谓词,支持异步与同步两种调用方式.
  • 支持其它异步任务的回调.
  • 连缀式调用方式,希望你喜欢.
  • 其实它还有更多,等待你去发现.

##使用

####1.添加引用

  • Eclipse
    下载jar文件Download,添加至项目的libs目录下.
  • Gradle
    在build.gradle文件中如下配置
dependencies {
      compile 'com.bsince.event:library:1.0.3'
  }

####2.配置 你需要在你项的Application的子类中(如果没有继承自该类,需要建类继承,并在Manifest文件中注册)的oncreate方法中进行相关参数的配置.

public class AppContext extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        HttpGlobalConfiguration globalConfiguration
                = new HttpGlobalConfiguration.Builder()
                .connectTimeOut(5000)
                .readTimeOut(5000)
                .bufferSize(2048)
                .debug(true)
                .endPoint("http://192.168.1.109:8080")
                .userAgent("Bsince/test/engine")
                .useCookie(true)
                .engineType(EngineType.Engine_Bsince)
                .threadSize(3)
                .defaultAllowRedirect(false)
                .keepAlive(true)
//              .proxy(...)
//              .urlRewriter(...)
//              .defaultSSLSocketFactory(...)
//              .defaultHostnameVerifier(...)
//              .defaultContentHandlerFactory(...)
//              .authenticator(...)
//              .cookieHandler(...)
//              .netCacheDir(...)
                //more you want ... 
                .retryCount(2)
                .addDefaultRequestProperty("customHeader", "customerHeaderValue")
                .build(this);
        EventPublisher.init(globalConfiguration);
    }
}

上面的每一项配置都不是必须的,因为程序会默认一个值,如果你不想改变它,可以直接像下面这样
```Java HttpGlobalConfiguration globalConfiguration= new HttpGlobalConfiguration.Builder().build(this); EventPublisher.init(globalConfiguration); ```

####3.调用 完成如上配置后,你就可以愉快地开发了。比如 #####Get请求

 EventPublisher.connect(String.class, "http://www.baidu.com")
                .tag("baidu")
                .submit(new ResponseListener<String>() {
                    @Override
                    public void onSuccessResponse(String s) {
                        editext.setText(s);
                    }
                    @Override
                    public void onErrorResponse(Exception e) {
                        editext.setText(e.toString());
                    }
                });

#####Post请求

        FormEncodeDataSet ds = new FormEncodeDataSet();
        ds.put("name", "张三");
        ds.put("pwd", "123456");
        EventPublisher.connect(String.class, "/HttpService/login")
                .data(ds)
                .method(Method.POST)
                .tag("login")
                .submit(new ResponseListener<String>() {
                    @Override
                    public void onSuccessResponse(String s) {
                        editext.setText(s);
                    }

                    @Override
                    public void onErrorResponse(Exception e) {
                        editext.setText(e.toString());
                    }
                });

注意:在使用EventPublisher.Connect("")时,未指定method将会被默认成GET请求,上面示例中FormEncodeDataset是用于封装请求参数的实体类,Get请求也可以使用.data()方法来指定请求参数,请求参数将默认以表单提交的方式追加到Url后面

如果你的返回类型不是String类型,你还必须为其指定一个parser作为解析器,我们为你提供以下几种默认的解析器,以便你针对不同情况时使用:

  • BitmapParserImp //默认解析后返回Bitmap对象
  • FileDownloadParser // 默认解析后返回文件对象
  • JSONArrayParserImp //抽象类,返回jsonArray由你去实现将其转换为javaBean对象
  • JSONObjectParserImp // 抽象类,返回JsonObject由你去实现将其转换为javaBean对象
  • SimpleParserImp //抽象类,返回String由你去实现将其转换为javaBean对象
  • TextParserImp //默认返回String字符串
  • XmlParserImp //抽象类,返回Xmlpullparser由你去实现将其转换为javaBean对象

如下是使用JSONObjectParserImp的示例

  EventPublisher.connect(User.class,"/login?....")
                .parser(new JSONObjectParserImp<User>() {
                    @Override
                    public User parsed(JSONObject object, Headers mHeaders) throws ParseException {
                        User u = new User();
                        u.name = object.optString("name");
                        u.value =object.optString("value");
                        return u;
                    }
                })
                .submit(new ResponseListener<User>() {
                    @Override
                    public void onSuccessResponse(User response) {
                        editext.setText(response.name); 
                    }
                    @Override
                    public void onErrorResponse(Exception error) {
                        editext.setText(e.toString());
                    }
                });

#####3. File Upload

BsinceEvent支持File与InputStream两种形式的文件上传

        MulitDataSet ds = new MulitDataSet();
        ds.put("title", "xxxxx");
        ds.put("videofile", file,filename);
        ds.put("stream", is, streamName);
        EventPublisher.connect(String.class, "/HttpService/upload")
                .method(Method.POST)
                .data(ds)
                .tag("upload")
                .submit(new ResponseListener<String>() {
                    @Override
                    public void onSuccessResponse(String s) {
                        editext.setText(s);
                        dialog.dismiss();
                    }
                    @Override
                    public void onErrorResponse(Exception e) {
                        dialog.dismiss();
                        editext.setText(e.toString());
                    }
                });

相信你也发现了,这里我们用的是MulitDataset来封装参数.是的我们为你提拱了以下几种Dataset的实现

  • JsonDataSet
    用来传输Json格式的字符参数
  • JsonStreamDataSet
    将文件流转化为Json形式上传,支持Gzip压缩
  • FormEncodeDataset
    普通的表单提交,支持集合类型
  • NameValueDataSet
    键值对型,与FormEncodeDataSet功能近似,支持集合类型,但集合若有序键会追加下标(eg:key[index])
  • SoapDataSet
    构建webService服务的请求参数,下面会提到

到这里,也许关于文件上传就差不多了,文件、流、都能上传,甚至可以Gzip压缩成Json字符串上传,如此说来确实很方便。但是? 是的这里存在一些问题:

  • 太大的文件最好不要通过Http协议上传(一般是2M),会崩的.怎么办呢?
    当然你可以改成ChunkingMode,BsinceEvent也支持这种方式,重写DataSet下面这个方法,并重写setpropertybeforeConnect,设置块大小.
@Override
	public boolean isChunkedStreamingMode() {
		return true;
	}
	@Override
	public void setPropertyBeforeConnect(HttpURLConnection conn) {
    conn.setChunkedStreamingMode(5); 
	}

当然我们更乐意你用另一种方式,我们额外提供了一个SocketClient;

SocketClient.doUpload("http://192.168.1.109:8080/HttpService/upload",map, new MulitDataSet.FileWrapper[]{new MulitDataSet.FileWrapper(f,null,"xiong.jpg")},new LoadingListener() {
            @Override
            public void onLoadingStarted() {
                Log.e("load","onLoadingStarted");
            }

            @Override
            public void onLoadProgressChanged(int i, int i2) {
                Log.e("load","onLoadProgressChanged"+i+"/"+i2);
            }

            @Override
            public void onLoadingError(Exception e) {
                Log.e("load","onLoadingError");
                dialog.dismiss();
            }

            @Override
            public void onLoadingEnd(boolean b, Object... objects) {
                Log.e("load","onLoadingEnd");
                dialog.dismiss();
            }
        });
  • 如何监听上传进度?
    是的,相信你也发现了,用Socket上传还能监听到上传进度。是的,因为这里我们只实现了socket文件的上传,而文件的总长度是可知的,所以监听到其上传进度并不意外。实现上,如果你使用Mulitdataset,也只向里面添加了文件,而没有流的话,也是可以实现监听的。
        MulitDataSet ds = new MulitDataSet();
        ds.put("title", "xxx文件");
        ds.put("timelength", "15");
        try {
            ds.put("videofile", new File(Environment.getExternalStorageDirectory(), "xiong.jpg"));
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            editext.setText(e.toString());
            return;
        }
        ds.setProgressChangeListener(new ProgressChangeListener() {
            @Override
            public void onLoadProgressChanged(int currentSize, int totalSize) {
                Log.d("Sample",currentSize+"/"+totalSize);
            }
        });
        EventPublisher.connect(String.class, "/HttpService/upload")
                .method(Method.POST)
                .data(ds)
                .tag("upload")
                .submit(new ResponseListener<String>() {
                    @Override
                    public void onSuccessResponse(String s) {
                        editext.setText(s);
                        dialog.dismiss();
                    }

                    @Override
                    public void onErrorResponse(Exception e) {
                        dialog.dismiss();
                        editext.setText(e.toString());
                    }
                });

好了,文件上传部份暂时就到这里 #####4.WebService请求 有时其实会遇到这样的情况,需要向一些公众支持接口调取服务,比如天气,归属地等,它们一般都是以webservice服务,这时你大可不必担忧,因为这里提供了一种Dataset的实现

  • doNet平台
        SoapDataSet ds = new SoapDataSet(SoapDataSet.SOAP_VER_12);
        ds.setMethodName("getSupportCity");
        ds.setNameSpace("http://WebXml.com.cn/");
        ds.setSoapAction("http://WebXml.com.cn/getSupportCity");
        ds.put("byProvinceName", "北京");
        ds.dotNet = true;
        EventPublisher.connect(String.class, "http://www.webxml.com.cn/WebServices/WeatherWebService.asmx")
                .data(ds)
                .method(Method.POST)
                .submit(new ResponseListener<String>() {
                    @Override
                    public void onSuccessResponse(String s) {
                        editext.setText(s);
                        dialog.dismiss();
                    }
                    @Override
                    public void onErrorResponse(Exception e) {
                        dialog.dismiss();
                        editext.setText(e.toString());
                    }
                });
  • 非doNet平台
         SoapDataSet ds2 = new SoapDataSet(SoapDataSet.SOAP_VER_11);
        ds2.setMethodName("getTempVerifiCode");
        ds2.setNameSpace("http://jdk.study.hermit.org/client");
        ds2.setSoapAction("");
        ds2.put("userCode", "42a3c56c9e45c968");
        ds2.put("password", "");
        ds2.put("userType", "02");
        ds2.dotNet = false;
        EventPublisher.connect(String.class, "http://wwww...........")
                .data(ds2)
                .method(Method.POST)
                .submit(new ResponseListener<String>() {
                    @Override
                    public void onSuccessResponse(String s) {
                        editext.setText(s);
                        dialog.dismiss();
                    }
                    @Override
                    public void onErrorResponse(Exception e) {
                        dialog.dismiss();
                        editext.setText(e.toString());
                    }
                });

#####5.Cookie 在配置Globalconfiguration时,useCookie设为true,将会自动处理Cookie; #####6.同步与异步 BsinceEvent在submit时,设置了对应回调ResponseListener时,为异步调用,不传入参数时,是为同步调用。

String s =EventPublisher.connect(String.class, "/HttpService/habit")
                        .data(ds)
                        .method(Method.POST)
                        .tag("habit")
                        .submit();

同时BsinceEvent还支持异步任务的调用

public static void submit(Event<?> task) {
     
}
EventPublisher.task().submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                Thread.sleep(2000);
                return "hello";
            }
        }, new ResponseListener<String>() {
            @Override
            public void onSuccessResponse(String response) {
                
            }
            @Override
            public void onErrorResponse(Exception error) {
            }
        });

#####7.图片的加载

EventPublisher.connect(Bitmap.class,"http://img0.bdstatic.com/img/image/f3165146edddf5807b7cb40a426ffaaf1426747348.jpg").bitmapExtras(0,0, Bitmap.Config.RGB_565)
                .cacheMode(CacheModel.CACHE_NEVER)
                .parser(BitmapParserImp.INSTANCE)
                .submit(new ResponseListener<Bitmap>() {
                    @Override
                    public void onSuccessResponse(Bitmap response) {
                        image.setImageBitmap(response);
                    }
                    @Override
                    public void onErrorResponse(Exception error) {
                        Toast.makeText(ListActivity.this,error.getMessage(),Toast.LENGTH_SHORT).show();
                    }
                });

在列表中显示图片,使用NetworkImageview

            NetworkImageView view = (NetworkImageView) convertView.findViewById(R.id.head);
            TextView tex= (TextView) convertView.findViewById(R.id.url);
            tex.setText(getItem(position));
            view.setDefaultImageResId(R.mipmap.ic_launcher);
            view.setImageUrl(getItem(position), imageLoader);

#####8.文件下载

 FileDownloadParser parser = new FileDownloadParser(Environment.getExternalStorageDirectory().getAbsolutePath(),"inst.exe");
EventPublisher.connect(File.class, "http://down.360safe.com/360/inst.exe")
                .parser(parser)
                .cacheMode(CacheModel.CACHE_NEVER)//禁用缓存
                .submit(new ResponseListener<File>() {
                    @Override
                    public void onSuccessResponse(File response) {
                        Toast.makeText(DownFileActivity.this,"下载成功",Toast.LENGTH_SHORT).show();
                    }
                    @Override
                    public void onErrorResponse(Exception error) {
                        Toast.makeText(DownFileActivity.this,"下载失败",Toast.LENGTH_SHORT).show();
                    }
                });

下载文件时,设置缓存模式为CacheModel.CACHE_NEVER
如果要监听下载进度,在parser中进行设置

        parser.setLoadingListener(new LoadingListener() {
            @Override
            public void onLoadingStarted() {

                Log.i("down","onLoadingStarted");
            }

            @Override
            public void onLoadProgressChanged(int currentSize, int totalSize) {
                Log.i("down","onLoadProgressChanged:"+currentSize+"/"+totalSize);
            }

            @Override
            public void onLoadingError(Exception e) {
                Log.i("down","onLoadingError:"+e.toString());
            }

            @Override
            public void onLoadingEnd(boolean complete, Object... args) {
                Log.i("down","onLoadingEnd");
            }
        });

#####9.Extras

  • 清除http磁盘缓存
EventPublisher.clearHttpCache(new Runnable() {
                @Override
                public void run() {
                    Toast.makeText(ListActivity.this,"缓存清除成功",Toast.LENGTH_SHORT).show();
                }
            });
  • 取消请求
        EventPublisher.cancel("tag");//通过标记请求
        EventPublisher.cancelAll();//取消全部
        EventPublisher.cancel(3);//通过序号取消
        EventPublisher.cancel(new EventFilter() {//自定义筛选条件取消
            @Override
            public boolean apply(Event<?> task) {
                return false;
            }
        });

目前项目中的注释大量‘清白’,主要是想全部改成英文注释,删完原先注释之后,才发现工作量不小,只能以后尽快补上了,若造成了你的不便,请谅解
如果你在使用过程中发现Bug或遇到什么问题,请与我联系 oeager@foxmail.com

About

Android异步网络开发框框

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages