再议Java/Android回调——由一段Bmob查询操作引发的思考

来源:互联网 发布:确认密码 javascript 编辑:程序博客网 时间:2024/06/11 02:03

最近小学弟有一个参赛项目出现个bug解决不了,前来问我。拿来代码一看,有Bmob后端云(PS:什么鬼,好像还不错的样子),其实就是将数据库操作封装过了,使用框架后只需要关注存取对象,不关心增删改查。

他的问题是有一个商品ID,通过商品ID查出拥有该商品的商店后在地图上标注出来(用的高德地图),相关代码如下:

    //获取满足条件的所有的商店    private void getShops(Integer productID)    {        final BmobQuery<Shop> shopBmobQuery=new BmobQuery<Shop>();        final BmobQuery<ProductNum> mProductNumquery=new BmobQuery<ProductNum>();        mProductNumquery.addWhereEqualTo("ProID",productID);        mProductNumquery.findObjects(new FindListener<ProductNum>() { // 商品与商店用ProductNum(对象)表关联            @Override            //查询成功调用            public void done(List<ProductNum> list, BmobException e) { // list包含了所有商店ID                if(e==null){                    if(list.size()==0){                        new AlertDialog.Builder(ShowShop2.this).setTitle("提示")//设置对话框标题                                .setMessage("抱歉,没有找到附近有该商品的商店")//设置显示的内容                                .setPositiveButton("确定",new DialogInterface.OnClickListener() {//添加确定按钮                                    @Override                                    public void onClick(DialogInterface dialog, int which) {//确定按钮的响应事件                                        finish();                                    }                                }).show();                    }                   //返回查到的商店ID                    for(ProductNum productNum:list ){                        //查询商店                        shopBmobQuery.addWhereEqualTo("ShopID",shopID);                        shopBmobQuery.findObjects(new FindListener<Shop>() {                            @Override                            public void done(List<Shop> list, BmobException e) {// 该list仅有一个元素                                for(Shop shop:list) {                                    if(!showone){ // 第一个商店显示在当前页                                        showone=true;                                        displayshopinfo(shop);                                        getShopInfo(shop);                                    }                                    addMarkersToMap(shop); // 给所有商店添加地图标记                                }                            }                        });                    }                }else{                    Log.i("bmob","失败:"+e.getMessage()+","+e.getErrorCode());                }            }        });    }
代码有点混乱,将就着看吧。他的问题是只能在地图上标记出一个商店(原本可以标记多个),调试插入log发现两次done()回调(此处的ProductNum的list只有两个元素)中的list均只包含同一个Shop(这里指字面值,不是指对象),所以调用addMarkersToMap()方法就只能在地图上标记一个商店。——这是为什么呢?下面看一段代码:

protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);final Button caller = (Button) findViewById(R.id.caller);for (int i = 0; i < 2; i++) {caller.setAlpha(i); // 改变alpha值caller.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubSystem.out.println("do some thing");}});}}

类比上面的代码,caller即是shopBmobQuery,caller.setAlpha()即是shopBmobQuery.addWhereEqualTo(),caller.setOnClickListener()即是shopBmobQuery.findObjects(),onClick()即是done()。caller中两次改变alpha值最终只是作用在一个对象上,设置的OnClickListener也只能是第二个监听器被回调,所以想要两个FindListener监听器被分别回调,必须让shopBmobQuery成为局部变量,即可以生成多个shopBmobQuery对象,分别注册不同的监听器。

所以修改后的代码为:

    //查询商店    BmobQuery<Shop> shopBmobQuery = new BmobQuery<Shop>();    shopBmobQuery.addWhereEqualTo("ShopID", local_shopID);    shopBmobQuery.findObjects(new FindListener<Shop>() {        @Override        public void done(List<Shop> list, BmobException e) {            Log.i("Mark", list.toString());            for (Shop shop : list) {                if (!showone) {                    showone = true;                    displayshopinfo(shop);                    getShopInfo(shop);                }                addMarkersToMap(shop);            }        }    });
由此可知,多次注册监听器,只有最终的那个监听器会被回调。

原创粉丝点击