Java 自定义回调函数(编写属于自己的SDK)

来源:互联网 发布:古装电影推荐 知乎 编辑:程序博客网 时间:2024/05/18 01:24

这几天,忙的跟狗一样了。

新公司,新的责任。

最近,公司的一个新项目。我的工作,是负责安卓端网络通信层的编写。

其实,说实话,安卓项目经验也不是非常多。也是边学边成长吧。

最开始,我只是做一个简单的编写,利用Xutils框架,做了一个最简单的封装。

public void send(HttpMethod method, String url, RequestParams params) {mHttpUtils.send(method, url, params, new RequestCallBack<String>() {@Overridepublic void onFailure(HttpException arg0, String arg1) {}@Overridepublic void onSuccess(ResponseInfo<String> arg) {}});}

说简单点,就是在框架上封装了一次,然后给业务层调用。

不过,项目经理看到这个以后,就屌我了:你这个不是网络通信层阿。只是一个方法而已。跟他进行沟通之后,了解到他的意思。他的想法是,业务层要进行网络通信时,只要调用某个业务,并传给参数给我,相应的url,请求方式t,都不是它关心的事。打个比方,现在有一个要登录的操作,业务层只要调用 login(参数)就可以了。

所以,我也在不停地尝试。

之后,回想到百度地图SDK中,有许多类似的例子。比如,现在我要做一个搜索Poi数据的操作,百度地图SDK也只有几步而已。

1:取得检索实例

2:设置监听

3:发起检索

简单的代码示例如下:

//取得Poi检索实例mPoiSearch =PoiSearch.newInstance();//设置监听mPoiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener() {            @Override            public void onGetPoiResult(PoiResult result) {                          }            @Override            public void onGetPoiDetailResult(PoiDetailResult result) {                       });//发起检索mPoiSearch.searchInCity(new PoiCitySearchOption().city("北京").keyword("餐厅").pageNum(1).pageCapacity(10)); 
由百度地图的SDK,我突然想到,是不是,我也能参照这样的步骤,做一个类似的SDK,给业务层调用呢。

然后,我就开始写代码。这里,我用到的是百度地图LBS云检索的API来做示例。

首先,我得有一个监听函数。那么,我就先写一个简单的接口。

/***@类名称:OnResultListener  *@类描述:  结果回调*@创建人:Yul_Wu  *@创建时间:2015年4月5日 下午10:08:15  *@修改人:Yul_Wu  *@修改时间:2015年4月5日 下午10:08:15  *@修改备注:  *@version   * */public interface OnResultListener {    void reDraw(String result,int error);}

然后,参照百度SDK的,我们还有一个检索的类GetBaiduSearch(以下称为检索类)

/** * *   *@项目名称:Result  *@类名称:GetBaiduSearch  *@类描述:  检索类*@创建人:Yul_Wu  *@创建时间:2015年4月5日 下午10:11:02  *@修改人:Yul_Wu  *@修改时间:2015年4月5日 下午10:11:02  *@修改备注:  *@version   * */public class GetBaiduSearch {private static GetBaiduSearch baiduSearch;private GetBaiduSearch() {}/** * 取得实例 *  * @return */public static GetBaiduSearch getInstance() {if (baiduSearch == null) {synchronized (GetBaiduSearch.class) {baiduSearch = new GetBaiduSearch();}}return baiduSearch;}

可以看到,这是一个非常简单的单例模式,通过getInstance()的方法,我们可以取得该类的实例。那们,我们还要有一个设置监听的方法,就叫setOnResultListener好了,那么代码就成这样了

public class GetBaiduSearch {    OnResultListener listener = null;    private static GetBaiduSearch baiduSearch;    private GetBaiduSearch() {    }    /**     * 取得实例     *      * @return     */    public static GetBaiduSearch getInstance() {        if (baiduSearch == null) {            synchronized (GetBaiduSearch.class) {                baiduSearch = new GetBaiduSearch();            }        }        return baiduSearch;    }    public void setOnResultListener(OnResultListener listener) {<p>        this.listener = listener;</p><p>        this.listener.reDraw(“要回调的具体内容”, 0);</p>    }<pre name="code" class="java">

这样,我们一个简单的回调函数,以及简单方法就写好了。接下来,我们来测试一下,在MainActivity中,我们做一个非常简单的测试。
mSearch= GetBaiduSearch.getInstance();button.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {mSearch.setOnResultListener(new OnResultListener() {@Overridepublic void reDraw(String result, int error) {// TODO Auto-generated method stubLog.v("yul_wu", result);}});}});

我们运行程序,点击Button,可以看到logcat上的输出:


这说明我们的数据成功返回了。

那么,接下来呢,我们再给检索类加上一个方法,也就是我们检索的主入口。

public void searchGeoTable() {                //这里用的是百度地图LBS云检索的例子,把通过API获得的数据返回给我们的监听函数                HttpUtils utils = new HttpUtils();RequestParams params = new RequestParams();String url = "http://api.map.baidu.com/geodata/v3/geotable/list";params.addQueryStringParameter("ak", "百度地图的ak");utils.send(HttpMethod.GET, url, params, new RequestCallBack<String>() {@Overridepublic void onFailure(HttpException arg0, String result) {}@Overridepublic void onSuccess(ResponseInfo<String> result) {if (result.statusCode == 0 || result.statusCode == 200) {}}});}
那么,我们修改一下MainActivity中的代码:

mSearch= GetBaiduSearch.getInstance();        mSearch.setOnResultListener(new OnResultListener() {                        @Override            public void reDraw(String result, int error) {                Log.v("yul_wu", result);            }        });        button.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                mSearch.searchGeoTable();            }        });

可以看到,我们做完这些修改以后,是不是就跟百度SDK中的代码操作是不是一样了。


那么,接下来,我们怎么把通过http请求的数据回传给我们的调用处呢。最初的想法,我是在检索类中,我们定义一个变量result,然后再上面的OnSuccess中,去设置result的值,改完之后的代码如下:

private void setResult(String str){this.result = str;}public void setOnResultListener(OnResultListener listener) {this.listener = listener;this.listener.reDraw(this.result, 0);}public void SearchGeoTable() {HttpUtils utils = new HttpUtils();RequestParams params = new RequestParams();String url = "http://api.map.baidu.com/geodata/v3/geotable/list";params.addQueryStringParameter("ak", "你的百度AK");utils.send(HttpMethod.GET, url, params, new RequestCallBack<String>() {@Overridepublic void onFailure(HttpException arg0, String result) {}@Overridepublic void onSuccess(ResponseInfo<String> result) {if (result.statusCode == 0 || result.statusCode == 200) {setResult(result.result);}}});}

也就是我们在网络请求中,设置了result的值,然后再回传。接下来我们运行,发现,报空指针了.....惊恐

看这个错误日志,是说Log里的result是空的,而且,在我还没有点击按钮的时候,就已经报错了。这是为什么呢。其实,是我自己发蒙了。因为设置监听函数的时候,已经执行了redeaw这个方法了。所以,这个方法不能放在这里。那应该放在哪呢。(当然放在onSuccess方法中阿,这个简单你都不知道,博主是不是傻了。)

其实,我真是傻了。因为,代码写太多,脑子都乱掉了。我们再做一下修改,把redraw方法放在网络请求成功后的方法里,把没用的删掉,就成这样了。

public class GetBaiduSearch {    OnResultListener listener = null;    private static GetBaiduSearch baiduSearch;    private GetBaiduSearch() {    }    /**     * 取得实例     *      * @return     */    public static GetBaiduSearch getInstance() {        if (baiduSearch == null) {            synchronized (GetBaiduSearch.class) {                baiduSearch = new GetBaiduSearch();            }        }        return baiduSearch;    }    /**     * 设置监听     * @param listener     */    public void setOnResultListener(OnResultListener listener) {        this.listener = listener;    }    public void searchGeoTable() {        HttpUtils utils = new HttpUtils();        RequestParams params = new RequestParams();        String url = "http://api.map.baidu.com/geodata/v3/geotable/list";        params.addQueryStringParameter("ak", "你的百度AK");        utils.send(HttpMethod.GET, url, params, new RequestCallBack<String>() {            @Override            public void onFailure(HttpException arg0, String result) {            }            @Override            public void onSuccess(ResponseInfo<String> result) {                if (result.statusCode == 0 || result.statusCode == 200) {                    listener.reDraw(result.result, 0);                }            }        });    }}
然后,我们运行程序,程序没有报错吧。接下来,我们点击Buttou,是不是结果成功返回了!

如果做过百度LBS云开发的朋友,看到这个字符串肯定不陌生哈。说明我们的数据已经成功能过我们的回调函数返回了。这样,我们就完成了一个简单的模型。

接下来,我们再做一步封装,把参数封装成百度SDK的样子,

public class BaiduSearchOptions {private String ak;public BaiduSearchOptions() {}public BaiduSearchOptions ak(String ak) {this.ak = ak;return this;}}
这样,我们再把检索类中的方法修改一下,

public void SearchGeoTable(BaiduSearchOptions option) {HttpUtils utils = new HttpUtils();                //通过反射,取得参数里的值和字段名                RequestParams params = option.reflect(option);                String url = "http://api.map.baidu.com/geodata/v3/geotable/list";utils.send(HttpMethod.GET, url, params, new RequestCallBack<String>() {@Overridepublic void onFailure(HttpException arg0, String result) {}@Overridepublic void onSuccess(ResponseInfo<String> result) {if (result.statusCode == 0 || result.statusCode == 200) {listener.reDraw(result.result, 0);}}});}}
看一下我们的reflect方法:

public RequestParams reflect(Object obj) {RequestParams params = new RequestParams();String key =null;String value =null;if (obj == null)params= null;Field[] fields = obj.getClass().getDeclaredFields();for (int j = 0; j < fields.length; j++) {fields[j].setAccessible(true);// 字段名key = fields[j].getName();System.out.print(fields[j].getName() + ":");// 字段值if (fields[j].getType().getName().equalsIgnoreCase("java.lang.String")) {try {value=fields[j].get(obj).toString();System.out.print(fields[j].get(obj) + "     ");} catch (Exception e) {e.printStackTrace();}}}params.addQueryStringParameter(key,value);return params;}
那么,我们检索的时候,是不是就变成这样了:

BaiduSearchOptions options = new BaiduSearchOptions().ak("你的百度AK");mSearch.SearchGeoTable(options);

现在看一下,是不是就跟百度SDK检索的操基本一样了。这样,以后业务层调用的时候,只要给出参数,我们就可以把结果回传给调用者。调用于就不用去考虑Http请求那些东西了。当然,你还可以根据不同的业务,再次把返回的result进行封装,这里我就不多做介绍了。

好了,那么关于回调函数的内容就到这里了!

完整代码下载:下载源码

转载请注明出处:http://blog.csdn.net/ryffic/article/details/44891899

我的个人博客:http://www.mycaffe.cn,欢迎各位大牛前来指导!!

1 0
原创粉丝点击