Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android 寫行為日志到SD卡 並發處理 異步寫入數據到文件不影響界面響應時間

android 寫行為日志到SD卡 並發處理 異步寫入數據到文件不影響界面響應時間

編輯:關於Android編程


公司在做一個項目 要求記錄用戶行為,寫行為日志文件到SD卡。實現思想 不影響界面用戶體驗,要時時記錄日志 不能漏掉。

1.並發處理日志 寫一個類負責管理各個線程傳過來的日志數據,日志數據放在隊列中等待寫線程去處理。這裡每次添加一條日志數據都會檢查寫日志線程是否在工作,同時為了並發處理傳過來的數據采用synchronized 同步:

ConcurrentLinkedQueue 是基於鏈接節點的、線程安全的隊列。並發訪問不需要同步。因為它在隊列的尾部添加元素並從頭部刪除它們,所以只要不需要知道隊列的大小, ConcurrentLinkedQueue 對公共集合的共享訪問就可以工作得很好。收集關於隊列大小的信息會很慢,需要遍歷隊列 建議使用 if(!queue.isEmpty()) 判斷是否空

package com.xx.log;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.ConcurrentLinkedQueue;

import org.apache.log4j.Logger;
import org.apache.log4j.spi.LoggerFactory;

import android.util.Log;
/**
 * 行為日志記錄
 * @author Administrator
 *
 */
public class ActionLog { 
	protected final static Logger logger = Logger.getLogger(ActionLog.class);
	public static String filePath="";
	
	public static ConcurrentLinkedQueue tempQueue=new ConcurrentLinkedQueue();
	/**
     * 記錄基本信息 頭
     * @param bi
     */
    public static synchronized void recordBaseInfoLog(BaseInfo bi){  
    	tempQueue.add(bi);   
    	 if(!WriteThread.isWriteThreadLive){//監察寫線程是否工作中,沒有 則創建
    		 new WriteThread().start();
    	 } 
    }
    /**
     * 記錄行為信息
     * @param ai
     */
    public static synchronized void recordActionInfoLog(ActionInfo ai){
    	tempQueue.add(ai);
		 if(!WriteThread.isWriteThreadLive){
			 new WriteThread().start();
		 } 
    }
	/**
	 * 打開日志文件並寫入日志
	 * 
	 * @return
	 * **/
	public static void recordStringLog(String text) {// 新建或打開日志文件  
		File file = new File(filePath);
		if (!file.exists()) { 
			file.getParentFile().mkdirs();
			try {
				file.createNewFile();
			} catch (IOException e) {
				logger.error("行為日志:在"+filePath+"創建文件失敗!");
				e.printStackTrace();
			}
		}  
		try {
			FileWriter filerWriter = new FileWriter(file, true);//後面這個參數代表是不是要接上文件中原來的數據,不進行覆蓋
			BufferedWriter bufWriter = new BufferedWriter(filerWriter);
			bufWriter.write(text);
			bufWriter.newLine();
			bufWriter.close();
			filerWriter.close();
			Log.d("行為日志寫入成功",text);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	} 
	/**
	 * 判斷日志文件是否存在
	 * @return
	 */
    public static boolean isExitLogFile(){
    	File file = new File(filePath);
		if (file.exists()&&file.length()>3){
			return true;
		}else{
			return false;
		}
    }
    /**
     * 刪除日志文件
     */
    public static void deleteLogFile(){
	   File file = new File(filePath);
	   if (file.exists()){
		   file.delete();
	   }
    }  
} 

2.異步寫數據到文件 不影響用戶體驗,不能因為寫日志而有任何延遲.(實驗中如果一次寫入文件中的數據比較小,即使同步寫入也不會太慢)為了達到這一目的首先考慮多線程另起一個線程專門負責來寫日志到文件中代碼如下:

package com.xx.log;

import com.google.gson.Gson;

public class WriteThread extends Thread{

	public static boolean isWriteThreadLive=false;//寫日志線程是否已經在運行了
 
	public WriteThread() {
		isWriteThreadLive=true;
	}
	
	@Override
	public void run() {
		isWriteThreadLive=true;
		Gson gson=new Gson();     
		  while(!ActionLog.tempQueue.isEmpty()){//對列不空時
			try {
				//寫日志到SD卡
				ActionLog.recordStringLog(gson.toJson(ActionLog.tempQueue.poll())); 
			} catch (Exception e) { 
				e.printStackTrace(); 
			}
		} 
	   isWriteThreadLive=false;//隊列中的日志都寫完了,關閉線程(也可以常開 要測試下)
	} 
}

其實我覺得 寫線程還是要一直保持運行可能更好,頻繁的創建線程對象應該也很耗費性能

好了以上代碼經過測試 可以達到多個線程大量並發寫日志,可以保證按順序寫入到文件中,而不影響用戶體驗 反應時間用戶感覺上可以忽略不計

由於時間問題 我還要寫上傳日志的處理,寫日志的功能暫時先這樣,以後有時間了研究下保持寫線程一直live 直到整個程序結束。還有進過測試 能提升多少性能是否有這個必要。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved