oschina-app 源碼分析-數據緩存(離線功能)

         以前做過數據緩存的項目,也就是實現離線操作。當時剛開始做項目,我們都沒什麼經驗,但是緩存數據無非是數據庫或者文件,但是我們選擇用xml文件來存儲數據,現在看來是有點走遠路了,oschina-app通過實現對object的實體流讀寫來完成數據緩存,來看下顯現流程。

1,首先在ui線程中另起線程,獲取數據:

	/**
	 * 線程加載帖子數據
	 * 
	 * @param catalog
	 *            分類
	 * @param pageIndex
	 *            當前頁數
	 * @param handler
	 *            處理器
	 * @param action
	 *            動作標識
	 */
	private void loadLvQuestionData(final int catalog, final int pageIndex,
			final Handler handler, final int action) {
		mHeadProgress.setVisibility(ProgressBar.VISIBLE);
		new Thread() {
			public void run() {
				Message msg = new Message();
				boolean isRefresh = false;
				if (action == UIHelper.LISTVIEW_ACTION_REFRESH
						|| action == UIHelper.LISTVIEW_ACTION_SCROLL)
					isRefresh = true;
				try {
					PostList list = appContext.getPostList(catalog, pageIndex,
							isRefresh);
					msg.what = list.getPageSize();
					msg.obj = list;
				} catch (AppException e) {
					e.printStackTrace();
					msg.what = -1;
					msg.obj = e;
				}
				msg.arg1 = action;
				msg.arg2 = UIHelper.LISTVIEW_DATATYPE_POST;
				if (curQuestionCatalog == catalog)
					handler.sendMessage(msg);
			}
		}.start();
	}

在AppContext中判斷是從本地緩存取還是從網絡獲取:

/**
	 * 帖子列表
	 * @param catalog
	 * @param pageIndex
	 * @return
	 * @throws ApiException
	 */
	public PostList getPostList(int catalog, int pageIndex, boolean isRefresh) throws AppException {
		PostList list = null;
		String key = "postlist_"+catalog+"_"+pageIndex+"_"+PAGE_SIZE;
		if(isNetworkConnected() && (!isReadDataCache(key) || isRefresh)) {		
			try{
				list = ApiClient.getPostList(this, catalog, pageIndex, PAGE_SIZE);
				if(list != null && pageIndex == 0){
					Notice notice = list.getNotice();
					list.setNotice(null);
					list.setCacheKey(key);
					saveObject(list, key);
					list.setNotice(notice);
				}
			}catch(AppException e){
				list = (PostList)readObject(key);
				if(list == null)
					throw e;
			}
		} else {
			list = (PostList)readObject(key);
			if(list == null)
				list = new PostList();
		}
		return list;
	}

根據程序判斷,如果是本地沒有走網絡獲取,並緩存到本地saveObject(list, key);,有則直接讀取list = (PostList)readObject(key);直接看上數據緩存和讀取的代碼:

/**
	 * 保存對象
	 * @param ser
	 * @param file
	 * @throws IOException
	 */
	public boolean saveObject(Serializable ser, String file) {
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try{
			fos = openFileOutput(file, MODE_PRIVATE);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(ser);
			oos.flush();
			return true;
		}catch(Exception e){
			e.printStackTrace();
			return false;
		}finally{
			try {
				oos.close();
			} catch (Exception e) {}
			try {
				fos.close();
			} catch (Exception e) {}
		}
	}
	
	/**
	 * 讀取對象
	 * @param file
	 * @return
	 * @throws IOException
	 */
	public Serializable readObject(String file){
		if(!isExistDataCache(file))
			return null;
		FileInputStream fis = null;
		ObjectInputStream ois = null;
		try{
			fis = openFileInput(file);
			ois = new ObjectInputStream(fis);
			return (Serializable)ois.readObject();
		}catch(FileNotFoundException e){
		}catch(Exception e){
			e.printStackTrace();
			//反序列化失敗 - 刪除緩存文件
			if(e instanceof InvalidClassException){
				File data = getFileStreamPath(file);
				data.delete();
			}
		}finally{
			try {
				ois.close();
			} catch (Exception e) {}
			try {
				fis.close();
			} catch (Exception e) {}
		}
		return null;
	}

現在看來確實很簡單,只要在請求前讀數據在請求後寫數據就行了。

網絡獲取部分就不說,沒什麼特殊的就是HttpClient,別忘了出來各種異常就行了。

oschina-app完整源碼下載:http://download.csdn.net/detail/xiangxue336/7023661

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章