指尖菜谱App从0到1-精选模块实现(1)

来源:互联网 发布:中国省市区数据库 编辑:程序博客网 时间:2024/05/08 18:53

前面几篇相关文章介绍了,项目的准备、初建等相关工作。这篇将用于介绍精选模块的实现。看了很多供应商提供的接口如Mob、阿凡达数据以及聚合接口。最后决定使用聚合数据提供的微信精选api。
选择聚合数据理由:简单实用;数据每天都有更新;免费。
其接口的申请地址,及相关介绍请详情https://www.juhe.cn/docs/api/id/147
1、微信精选接口说明
接口地址:public static final String WEIXIN_CHOICE = “http://v.juhe.cn/weixin/query“;
接口返回的json数据如下:

{    "reason": "success",    "result": {        "list": [            {                "id": "wechat_20150401071581",                "title": "号外:集宁到乌兰花的班车出事了!!!!!",                "source": "内蒙那点事儿",                "firstImg": "http://zxpic.gtimg.com/infonew/0/wechat_pics_-214279.jpg/168",                "mark": "",                "url": "http://v.juhe.cn/weixin/redirect?wid=wechat_20150401071581"            },            {                "id": "wechat_20150402028462",                "title": "【夜读】梁晓声:你追求的,就是你人生的意义",                "source": "人民日报",                "firstImg": "http://zxpic.gtimg.com/infonew/0/wechat_pics_-214521.jpg/168",                "mark": "",                "url": "http://v.juhe.cn/weixin/redirect?wid=wechat_20150402028462"            }        ],        "totalPage": 16,        "ps": 20,        "pno": 1    },    "error_code": 0}

从数据中可以很轻易的看出每一个字段,其中list下的数组正是我们需要的数据。更加其我们可以封装出一个对象,以供Gson进行解析。
这里起名为JuheWXChoice,具体代码如下

public class JuheWXChoice {    private int error_code;//返回码    private String reason;//返回说明    private Result result;//结果集    /********get & set************/    ...    public String getReason() {        return reason;    }    public class Result {        List<Content> list;    /********get & set************/    ...    }    public class Content {        private String id;        private String title;        private String source;//来源        private String firstImg;//缩略图        private String mark;        private String url;      /********get & set************/    ...        @Override        public String toString() {            return "Content{" +                    "id='" + id + '\'' +                    ", title='" + title + '\'' +                    ", source='" + source + '\'' +                    ", firstImg='" + firstImg + '\'' +                    ", mark='" + mark + '\'' +                    ", url='" + url + '\'' +                    '}';        }    }}

注意点:封装的对象属性名一定要与json数据的字段一致,private Result result属性的‘result’与json数据的‘result’相对应,如果把名字一变,将会出现解析异常。当然分装的对象中可以少,也就是说private String id;去了,依旧可以解析,只不过没有对象中没有id这属性了。

2、通过接口进行数据加载
更加接口的说明我们在进行get时需要传入的参数分别为key与pno,其它默认就行。
再此之前我们新建一个NetAction类,用于App中的所有数据加载工作,当然相关的加载我们还是得使用之前封装好的NetUtils类详情请看http://blog.csdn.net/it_faquir/article/details/52982494介绍。

 public void getJuheWXChoice(String page, final List<JuheWXChoice.Content> choice) {        Map<String, String> param = new HashMap<>();        param.put("key", "" + MyApplication.JUHE_KEY);        param.put("pno", "" + page);//第几页        NetUtils.get(NetUri.JUHE.WEIXIN_CHOICE, param, new StringCallback() {            @Override            public void onError(Call call, Exception e, int i) {            }            @Override            public void onResponse(String s, int i) {                Gson gson = new Gson();                JuheWXChoice juheWXChoice = gson.fromJson(s, JuheWXChoice.class);                choice.addAll(juheWXChoice.getResult().getList());                netLoadings.get(KUID_CHOICE_LIST).netLoadingComp(KUID_CHOICE_LIST);            }        });    }

我们会发现其中有个netLoadings.get(KUID_CHOICE_LIST).netLoadingComp(KUID_CHOICE_LIST);,这个的实现目的是为了在加载完数据后通知界面进行相应的更新。其实也这里用了观察者模式。
首先写一个接口,专门用于此。如下:

/** * 观察者模式网络加载专用接口,kuid作为某个事件的一个id。 */public interface NetLoadingListener {    void netLoadingComp(int kuid);}

你会好奇,kuid是干嘛的,其实作者目的是为了能够使此接口适用于不同环境的网络加载中,以kuid作为唯一标识,而不用重复写多个类似的接口。

在NetAction中我们需要如下Map用于存放NetLoadingListener,便可应用中kuid来找到对象的NetLoadingListener,进行相应的事件通知。

 private static Map<Integer, NetLoadingListener> netLoadings = new HashMap<>();    //添加网络加载事件    public static void addNetLoadingListener(int kuid, NetLoadingListener listener) {        netLoadings.put(kuid, listener);        System.out.println("add ok");    }

在ChoiceFragment的onCreate中实现实现相应的接口

    @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //添加监听器        NetAction.addNetLoadingListener(NetAction.KUID_CHOICE_LIST, this);        netAction = NetAction.newAction();        netAction.getJuheWXChoice("" + curPager, choiceList);    }    /**     * 监听器触发处,网络数据获取完成,触发此     * @param kuid     */    @Override    public void netLoadingComp(int kuid) {        if (kuid == NetAction.KUID_CHOICE_LIST) {            mAdapter.notifyDataSetChanged();        }    }

当数据加载成功后,netLoadingComp方法便被调用,此此时的List < JuheWXChoice.Content> choiceList引用的对象便不为空,且有数据,我们即可进行正常的显示数据。
3、利用RecycleView进行数据显示
根据加载的数据,我们可以设计item需要显示的内容:
这里写图片描述

因此我们可以对此进行相应的界面编写

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/choice_list"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:background="@color/colorWhite"    android:clickable="true"    android:elevation="2dp"    android:orientation="vertical"    android:padding="5dp">    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content">        <ImageView            android:id="@+id/choice_list_img"            android:layout_width="80dp"            android:layout_height="80dp" />        <TextView            android:id="@+id/choice_list_title"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignParentTop="true"            android:layout_marginLeft="10dp"            android:layout_toEndOf="@+id/choice_list_img"            android:layout_toRightOf="@+id/choice_list_img"            android:lines="3"            android:text="@string/app_name"            android:textColor="@color/colorBlack"            android:textSize="14sp" />        <TextView            android:id="@+id/choice_list_source"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:layout_alignParentEnd="true"            android:layout_alignParentRight="true"            android:layout_marginRight="10dp"            android:text="@string/app_name"            android:textSize="12sp" />    </RelativeLayout></LinearLayout>

在ChoiceFragment中进行相应的RecycleAdapter的编写与RecycleView显示即可,完整代码如下

/** * Created by hgs on 2016/10/26. */public class ChoiceFragment extends BaseFragment implements NetLoadingListener, MySwipe.OnUpLoadingListener, SwipeRefreshLayout.OnRefreshListener {    private static ChoiceFragment choiceFragment;    //数据    private List<JuheWXChoice.Content> choiceList = new ArrayList<>();    private NetAction netAction;    private int curPager = 1;//记录当前所显示的页    private ObjectAnimator animation;    private ChoiceRecycleAdapter mAdapter;    @BindView(R.id.main_bar_title)    TextView tvTitle;    @BindView(R.id.choice_recycle)    RecyclerView cRecycle;    @BindView(R.id.choice_mySwipe)    MySwipe mySwipe;    @BindView(R.id.loading_layout)    View loadingLayout;    @BindView(R.id.loading_icon)    ImageView loadingIcon;    public static ChoiceFragment newInstance() {        if (choiceFragment == null) {            choiceFragment = new ChoiceFragment();        }        return choiceFragment;    }    @Override    public void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //添加监听器        NetAction.addNetLoadingListener(NetAction.KUID_CHOICE_LIST, this);        netAction = NetAction.newAction();        netAction.getJuheWXChoice("" + curPager, choiceList);    }    @Nullable    @Override    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {        View view = inflater.inflate(R.layout.fragment_choice, container, false);        ButterKnife.bind(this, view);        initView();        return view;    }    private void initView() {        tvTitle.setText("指尖精选");        //recycleView        cRecycle.setLayoutManager(new LinearLayoutManager(getContext()));        mAdapter = new ChoiceRecycleAdapter(choiceList);        cRecycle.setAdapter(mAdapter);    }    /**     * 监听器触发处,网络数据获取完成,触发此     *     * @param kuid     */    @Override    public void netLoadingComp(int kuid) {        if (kuid == NetAction.KUID_CHOICE_LIST) {            mAdapter.notifyDataSetChanged();        }    }    @Override    public void scrollMoving(int scrollY, int distance) {        if (loadingLayout != null) {            loadingLayout.setVisibility(View.VISIBLE);            showUpLoadingAnim(loadingIcon);        }    }    class ChoiceRecycleAdapter extends RecyclerView.Adapter<MyAdapterHolder> {        List<JuheWXChoice.Content> choiceList;        ChoiceRecycleAdapter(List<JuheWXChoice.Content> choiceList) {            this.choiceList = choiceList;        }        @Override        public MyAdapterHolder onCreateViewHolder(ViewGroup parent, int viewType) {            View view = LayoutInflater.from(getContext()).inflate(R.layout.choice_list_layout, null);            return new MyAdapterHolder(view);        }        @Override        public void onBindViewHolder(MyAdapterHolder holder, int position) {            String imgUri = choiceList.get(position).getFirstImg();            if (imgUri == null || imgUri.isEmpty()) {                holder.listImg.setVisibility(View.GONE);            } else                netAction.loadImage(getContext(), choiceList.get(position).getFirstImg(), holder.listImg);            holder.listSource.setText("" + choiceList.get(position).getSource());            holder.listTitle.setText("" + choiceList.get(position).getTitle());            holder.setItemClickListener(choiceList.get(position).getUrl());        }        @Override        public int getItemCount() {            return choiceList.size();        }    }    class MyAdapterHolder extends RecyclerView.ViewHolder{        @BindView(R.id.choice_list_img)        ImageView listImg;        @BindView(R.id.choice_list_title)        TextView listTitle;        @BindView(R.id.choice_list_source)        TextView listSource;        @BindView(R.id.choice_list)        LinearLayout listLayout;        public MyAdapterHolder(View itemView) {            super(itemView);            ButterKnife.bind(this, itemView);        }        }}

需要注意的是,作者在这里使用了ButterKnife框架,通过注解的方式来简化了findViewById的方式,具体详情https://github.com/JakeWharton/butterknife。
好了我们来看看效果如何吧。
这里写图片描述

不过你会发现没法进行下拉刷新与上拉加载以及item的点击,查看详细的内容。后续请关注指尖菜谱App从0到1-精选模块实现(2)

0 0