電子市場項目總結(四)

電子市場項目總結(四)

1、網絡數據解析的封裝


這部分代碼沒有什麼靈活性可言,如果能熟練使用BaseAdapter的封裝,這裏對網絡數據的解析封裝相對就非常簡單了!

直接從代碼入手:

public abstract class BaseProtocol<T> {
    // 這裏是複習如何使用enum枚舉,因爲服務器中對請求有一下幾種所以封裝起來更方便使用
    public enum Key {
        category("category"), image("image"), recommend("recommend"), subject("subject"),
        detail("detail"), home("home"), app("app"), game("game"), download("download"),
        user("user"), hot("hot");

        String key;

        private Key(String key) {
            this.key = key;
        }

        public String getKey() {
            return this.key;
        }
    }

    private String mKey;

    /**
     * 根據position進行分頁查詢,
     * 此處的分頁查詢是因爲服務器已經支持分頁查詢的功能,因此只需要填充對應的position即可,
     * 這裏有一點,position在數據的連續的情況下可以直接使用list的總數,
     * 即調用者直接填充已經獲取的數據的個數。
     */
    public T getData(int position) {
        mKey = setKey().getKey();

        if (StringUtils.isEmpty(mKey))
            return null;

        mKey = mKey + "?index=" + position + getParams();
        // 先從本地緩存中讀取,如果沒有讀取到才網絡加載
        String dataString = readCache(position);

        if (StringUtils.isEmpty(dataString)) {
            dataString = readInternet(position);
        }

        return parseData(dataString);
    }

    /**
     * 提供給子類設置參數
     *
     */
    protected abstract String getParams();

    /**
     * 子類實現數據的解析
     *
     */
    protected abstract T parseData(String dataString);

    /**
     * 子類必須實現key,來確認訪問地址
     *
     */
    public abstract Key setKey();


    /**
     * 從網絡中獲取數據,這裏網絡的解析在HttpHelper類中被封裝好了,直接拿來使用即可,
     * HttpHelper中使用的HttpClient,api23以上需要導入path:sdk\platforms\android-23\optional\org.apache.http.legacy.jar包,當然也可使用其他新的框架來封裝。
     */
    private String readInternet(int position) {
        // 獲取連接對象
        HttpHelper.HttpResult httpResult = HttpHelper.get(HttpHelper.URL + mKey);
        // 獲取json數據
        String string = "";

        if (httpResult != null)
            string = httpResult.getString();

        LogUtils.i(string);

        // 如果非空
        if (!StringUtils.isEmpty(string)) {
            saveCache(string);
        }
        return string;
    }

    /**
     * 保存數據到本地,並添加有效期,添加有效期這裏可以有兩種方式,
     * 一種是直接添加截止期,讀取時判斷是否超過截止期,
     * 另一種是添加生成的日期,去讀時將讀取時間減去生成時間,判斷是否超過有效期。
     */
    private void saveCache(String data) {
        String cacheDir = MyApplication.getContext().getExternalCacheDir().getAbsolutePath() + File.separator + "jsondata";

        File file = new File(cacheDir);

        if (!file.exists()) {
            file.mkdirs();
            file.setReadable(true);
            file.setWritable(true);
        }
        FileWriter fileWriter = null;
        try {
            file = new File(file, CommonUtil.data2MD5(mKey, ""));
            if (file.exists()) {
                file.delete();
                file.createNewFile();
                file.setReadable(true);
                file.setWritable(true);
            }
            fileWriter = new FileWriter(file);
            // 寫上時間標記
//            fileWriter.write(System.currentTimeMillis()+30*1000*60+"\n"); 自帶截止日期
            fileWriter.write(System.currentTimeMillis() + "\n");
            fileWriter.write(data);
            fileWriter.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.close(fileWriter);
        }

    }

    /**
     * 從本地中讀取緩存
     */
    private String readCache(int position) {
        String data = "";
        String cacheDir = MyApplication.getContext().getExternalCacheDir().getAbsolutePath() + File.separator + "jsondata" + File.separator + CommonUtil.data2MD5(mKey, "");

        File file = new File(cacheDir);

        BufferedReader br = null;

        if (file.exists()) {
            try {
                br = new BufferedReader(new FileReader(file));
                // 讀取日期
                long date = Long.parseLong(br.readLine());
                // 在有效期內才使用
                if (System.currentTimeMillis() - date < 1800000) {
                    String line;
                    while ((line = br.readLine()) != null) {
                        data = data + line;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return data;
    }

}

那麼這些完成後,子類該實現的方法有:

  • protected abstract String getParams();// 提供給子類設置參數
  • protected abstract T parseData(String dataString);//子類實現數據的解析邏輯
  • public abstract Key setKey();//子類必須實現key,來確認訪問地址

2、開始實現一個Fragment


網絡協議也已經封裝完成子類只需要完成對網絡數據的解析即可,那麼開始將封裝完成的Protocol、BaseFragment、MyBaseAdapter以及BaseViewHolder結合起來就可以構建一個Fragment的了。
代碼如下:

public class AppFragment extends BaseFragment {

    private List<AppInfo> mListData = new ArrayList<>();
    private String tag = "AppFragment";
    private MyListView mMyListView;
    private InnerAdapter mAdapter;
    private AppProtocol mAppProtocol;

    /**
     * 數據的刷新會在fragment繪製之前被調用
     */
    protected State loadData() {
        if(mAppProtocol==null)
            mAppProtocol = new AppProtocol();

        mListData = mAppProtocol.getData(0);
        return checkLoad(mListData);
    }

    /**
        沒有使用到監聽     
    */
    protected void initListener() {
    // empty
    }

    /**
    完成一個佈局的記載,可以直接返回一個listView即可
    */
    public View initSuccessLayout() {
        mMyListView = new MyListView(mActivity);

        mAdapter = new InnerAdapter(mListData);
        mMyListView.setAdapter(mAdapter);

        return mMyListView;
    }

    /**
      我們已經完成BaseAdapter的封裝,所以我們只需要提供數據就可以實現數據的加載和展現
    */
    private class InnerAdapter extends MyBaseAdapter<AppInfo>{

        public InnerAdapter(List<AppInfo> mDataList) {
            super(mDataList);
        }

        @Override
        protected List<AppInfo> loadingMore() {
            if(mAppProtocol!=null)
                return mAppProtocol.getData(mListData.size());
            return null;
        }

        @Override
        protected BaseViewHolder<AppInfo> getBaseViewHolder(int position) {
            return new AppHolder();
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章