开源中国学习(首页新闻资讯类的实现)

主页面的页面切换,使用了MyFragmentTabHost进行切换,首先建立五个MianTab,依次创建VIew添加进去;
开源中国源码学习UI篇(一)之FragmentTabHost的使用分析

public enum MainTab {

    NEWS(0, "综合", R.drawable.tab_icon_new,
            NewsViewPagerFragment.class),

    TWEET(1, "动弹", R.drawable.tab_icon_tweet,
            TweetsViewPagerFragment.class),

    QUICK(2, "快速", R.drawable.tab_icon_new,
            null),

    EXPLORE(3, "发现", R.drawable.tab_icon_explore,
            ExploreFragment.class),

    ME(4, "我", R.drawable.tab_icon_me,
            MyInformationFragment.class);

    private int idx;
    private int resName;
    private int resIcon;
    private Class<?> clz;

    private MainTab(int idx, int resName, int resIcon, Class<?> clz) {
        this.idx = idx;
        this.resName = resName;
        this.resIcon = resIcon;
        this.clz = clz;
    }
}

封装基类

1.封装上层基类

综合界面

Fragement<-BaseFragment<-BaseViewPagerFragment<-NewsFragment
2.放入缓存列表
BaseApplication.java

 /**
     * 放入已读文章列表中
     *
     */
    public static void putReadedPostList(String prefFileName, String key,
                                         String value) {
        SharedPreferences preferences = getPreferences(prefFileName);
        int size = preferences.getAll().size();
        Editor editor = preferences.edit();
        if (size >= 100) {
            editor.clear();
        }
        editor.putString(key, value);
        apply(editor);
    }

读取已读文章

/**
     * 读取是否是已读的文章列表
     *
     * @return
     */
    public static boolean isOnReadedPostList(String prefFileName, String key) {
        return getPreferences(prefFileName).contains(key);
    }

3.是否到时间刷新数据

// 是否到时间去刷新数据了
    private boolean onTimeRefresh() {
        String lastRefreshTime = AppContext.getLastRefreshTime(getCacheKey());
        String currTime = StringUtils.getCurTimeStr();
        long diff = StringUtils.calDateDifferent(lastRefreshTime, currTime);
        return needAutoRefresh() && diff > getAutoRefreshTime();
    }

4.操作数据库的时候用AsyncTask

网路获取

以NewsFragment的网络获取为例

  • 在BaseListFragment写好一个protected的requestData方法实现网络获取:
 /**BaseListFragment**/
protected void requestData(boolean refresh) {
        String key = getCacheKey();
        if (isReadCacheData(refresh)) {
            readCacheData(key);
        } else {
            // 取新的数据
            sendRequestData();
        }
    }
  • NewsFragment继承了这个类,复写这个方法,调用网络交互的类进行网络交互
 /**NewsFragment继承了这个类,复写这个方法,调用网络交互的类进行网络交互**/
 @Override
    protected void sendRequestData() {
        OSChinaApi.getNewsList(mCatalog, mCurrentPage, mHandler);
    }
  • 之后mHandler这个对象创建在BaseListFragment,在这里完成网络获取,并开启线程将数据保存数据库
 protected AsyncHttpResponseHandler mHandler = new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int statusCode, Header[] headers,
                byte[] responseBytes) {
            if (mCurrentPage == 0 && needAutoRefresh()) {
                AppContext.putToLastRefreshTime(getCacheKey(),
                        StringUtils.getCurTimeStr());
            }
            if (isAdded()) {
                if (mState == STATE_REFRESH) {
                    onRefreshNetworkSuccess();
                }
                //进行数据的解析
                executeParserTask(responseBytes);
            }
        }

        @Override
        public void onFailure(int arg0, Header[] arg1, byte[] arg2,
                Throwable arg3) {
            if (isAdded()) {
                readCacheData(getCacheKey());
            }
        }
    };
  • 其中executeParserTask(responseBytes)方法里调用了
 private void executeParserTask(byte[] data) {
        cancelParserTask();
        mParserTask = new ParserTask(data);
        mParserTask.execute();
    }
  • 成功将数据保存进数据库后的操作
    class ParserTask extends AsyncTask<Void, Void, String> {

        private final byte[] reponseData;
        private boolean parserError;
        private List<T> list;

        public ParserTask(byte[] data) {
            this.reponseData = data;
        }

        @Override
        protected String doInBackground(Void... params) {
            try {
                ListEntity<T> data = parseList(new ByteArrayInputStream(
                        reponseData));
                new SaveCacheTask(getActivity(), data, getCacheKey()).execute();
                list = data.getList();
                if (list == null) {
                    ResultBean resultBean = XmlUtils.toBean(ResultBean.class,
                            reponseData);
                    if (resultBean != null) {
                        mResult = resultBean.getResult();
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();

                parserError = true;
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            //parserError代表解析错
            if (parserError) {
                readCacheData(getCacheKey());
            } else {
            //当没有数据的时候,重新进行网络获取
                executeOnLoadDataSuccess(list);
                executeOnLoadFinish();
            }
        }
    }
  • 数据获取成功后,进行数据展示
    protected void executeOnLoadDataSuccess(List<T> data) {
        if (data == null) {
            data = new ArrayList<T>();
        }

        if (mResult != null && !mResult.OK()) {
            AppContext.showToast(mResult.getErrorMessage());
            // 注销登陆,密码已经修改,cookie,失效了
            AppContext.getInstance().Logout();
        }

        mErrorLayout.setErrorType(EmptyLayout.HIDE_LAYOUT);
        if (mCurrentPage == 0) {
            mAdapter.clear();
        }

        for (int i = 0; i < data.size(); i++) {
            if (compareTo(mAdapter.getData(), data.get(i))) {
                data.remove(i);
                i--;
            }
        }
        int adapterState = ListBaseAdapter.STATE_EMPTY_ITEM;
        if ((mAdapter.getCount() + data.size()) == 0) {
            adapterState = ListBaseAdapter.STATE_EMPTY_ITEM;
        } else if (data.size() == 0
                || (data.size() < getPageSize() && mCurrentPage == 0)) {
            adapterState = ListBaseAdapter.STATE_NO_MORE;
            mAdapter.notifyDataSetChanged();
        } else {
            adapterState = ListBaseAdapter.STATE_LOAD_MORE;
        }
        mAdapter.setState(adapterState);
        mAdapter.addData(data);
        // 判断等于是因为最后有一项是listview的状态
        if (mAdapter.getCount() == 1) {

            if (needShowEmptyNoData()) {
                mErrorLayout.setErrorType(EmptyLayout.NODATA);
            } else {
                mAdapter.setState(ListBaseAdapter.STATE_EMPTY_ITEM);
                mAdapter.notifyDataSetChanged();
            }
        }
    }
  • 从数据库中读取
  private void readCacheData(String cacheKey) {
        cancelReadCacheTask();
        mCacheTask = new CacheTask(getActivity()).execute(cacheKey);
    }
  • 读取成功后再次进行数据展示
private class CacheTask extends AsyncTask<String, Void, ListEntity<T>> {
        private final WeakReference<Context> mContext;

        private CacheTask(Context context) {
            mContext = new WeakReference<Context>(context);
        }

        @Override
        protected ListEntity<T> doInBackground(String... params) {
            Serializable seri = CacheManager.readObject(mContext.get(),
                    params[0]);
            if (seri == null) {
                return null;
            } else {
                return readList(seri);
            }
        }

        @Override
        protected void onPostExecute(ListEntity<T> list) {
            super.onPostExecute(list);
            if (list != null) {
                executeOnLoadDataSuccess(list.getList());
            } else {
                executeOnLoadDataError(null);
            }
            executeOnLoadFinish();
        }
    }

动弹界面

  • 支持的人会显示在图片下面
public void setLikeUsers(Context contet, TextView likeUser, boolean limit) {
        // 构造多个超链接的html, 通过选中的位置来获取用户名
        if (getLikeCount() > 0 && getLikeUser() != null
                && !getLikeUser().isEmpty()) {
            likeUser.setVisibility(View.VISIBLE);
            likeUser.setMovementMethod(LinkMovementMethod.getInstance());
            likeUser.setFocusable(false);
            likeUser.setLongClickable(false);
            likeUser.setText(addClickablePart(contet, limit), BufferType.SPANNABLE);
        } else {
            likeUser.setVisibility(View.GONE);
            likeUser.setText("");
        }
    }
  • 点赞的操作,显示下列的人
/**
     * @return
     */
    private SpannableStringBuilder addClickablePart(final Context context,
                                                    boolean limit) {

        StringBuilder sbBuilder = new StringBuilder();
        int showCunt = getLikeUser().size();
        if (limit && showCunt > 4) {
            showCunt = 4;
        }

        // 如果已经点赞,始终让该用户在首位
        if (getIsLike() == 1) {

            for (int i = 0; i < getLikeUser().size(); i++) {
                if (getLikeUser().get(i).getId() == AppContext.getInstance()
                        .getLoginUid()) {
                    getLikeUser().remove(i);
                }
            }
            getLikeUser().add(0, AppContext.getInstance().getLoginUser());
        }

        for (int i = 0; i < showCunt; i++) {
            sbBuilder.append(getLikeUser().get(i).getName()).append("、");
        }

        String likeUsersStr = sbBuilder.substring(0, sbBuilder.lastIndexOf("、"));

        // 第一个赞图标
        // ImageSpan span = new ImageSpan(AppContext.getInstance(),
        // R.drawable.ic_unlike_small);
        SpannableString spanStr = new SpannableString("");
        // spanStr.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);

        SpannableStringBuilder ssb = new SpannableStringBuilder(spanStr);
        ssb.append(likeUsersStr);

        String[] likeUsers = likeUsersStr.split("、");

        if (likeUsers.length > 0) {
            // 最后一个
            for (int i = 0; i < likeUsers.length; i++) {
                final String name = likeUsers[i];
                final int start = likeUsersStr.indexOf(name) + spanStr.length();
                final int index = i;
                ssb.setSpan(new ClickableSpan() {
                    @Override
                    public void onClick(View widget) {
                        User user = getLikeUser().get(index);
                        UIHelper.showUserCenter(context, user.getId(),
                                user.getName());
                    }

                    @Override
                    public void updateDrawState(TextPaint ds) {
                        super.updateDrawState(ds);
                        // ds.setColor(R.color.link_color); // 设置文本颜色
                        // 去掉下划线
                        ds.setUnderlineText(false);
                    }
                }, start, start + name.length(), 0);
            }
        }
        if (likeUsers.length < getLikeCount()) {
            ssb.append("等");
            int start = ssb.length();
            String more = getLikeCount() + "人";
            ssb.append(more);
            ssb.setSpan(new ClickableSpan() {

                @Override
                public void onClick(View widget) {
                    Bundle bundle = new Bundle();
                    bundle.putInt(BaseListFragment.BUNDLE_KEY_CATALOG, getId());
                    UIHelper.showSimpleBack(context,
                            SimpleBackPage.TWEET_LIKE_USER_LIST, bundle);
                }

                @Override
                public void updateDrawState(TextPaint ds) {
                    super.updateDrawState(ds);
                    // ds.setColor(R.color.link_color); // 设置文本颜色
                    // 去掉下划线
                    ds.setUnderlineText(false);
                }

            }, start, start + more.length(), 0);
            return ssb.append("觉得很赞");
        } else {
            return ssb.append("觉得很赞");
        }
    }

学习心得:采用了父类的借口回调,在父类创建抽象的方法,利用子类实现,减少了子类的代码编写量。在父类可以封装不同的代码,提高了代码的复用率。在界面跳转的时候进行统一管理,代码也更加简单。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值