Android學習(22)-實戰要點

在實際項目中,合理的項目結構是非常重要的,下面講一下一般的結構形式。


各種包和類的作用:

activity: 活動相關代碼

db: 數據庫操作相關代碼

model: 模型,簡單實體類代碼

receiver: 廣播接收器相關代碼

service: 服務相關代碼

util: 工具相關代碼


1、db中如何合理設計代碼結構?

RealProjectOpenHelper類,繼承自SQLiteOpenHelper類,用於創建數據庫和各種表。

RealProjectDB類,最好是單例模式,各種操作數據庫的函數,如增刪改查功能。藉助於RealProjectOpenHelper類獲取數據庫操作句柄。

public class RealProjectOpenHelper extends SQLiteOpenHelper {

	//創建三個數據表的語句
	public static final String CREATE_PROVINCE = "create table Province(id integer primary key autoincrement, province_name text, province_code text)";	
	public static final String CREATE_CITY = "create table City(id integer primary key autoincrement, city_name text, city_code text, province_id integer)";	
	public static final String CREATE_COUNTY = "create table County(id integer primary key autoincrement, county_name text, county_code text, city_id integer)";
	
	//構造函數
	public RealProjectOpenHelper(Context context, String name, CursorFactory factory, int version){
		super(context, name, factory, version);
	}
	
	//數據庫創建
	@Override
	public void onCreate(SQLiteDatabase db) {
		db.execSQL(CREATE_PROVINCE);
		db.execSQL(CREATE_CITY);
		db.execSQL(CREATE_COUNTY);
	}

	//涉及到更新,此處的更新還是比較弱  參考之前的博文  知道如何更好的控制更新內容
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		db.execSQL("drop table if exists Province");  
		db.execSQL("drop table if exists City");
		db.execSQL("drop table if exists County");  
	    onCreate(db); 
	}

}

以及:

public class RealProjectDB {
	//數據庫名字
	public static final String DB_NAME = "cool_weather";
	//數據庫版本
	public static final int VERSION = 1;
	
	//單例模式使用
	private static RealProjectDB realprojectDB;
	
	private SQLiteDatabase db;
	
	private RealProjectDB(Context context){
		//創建數據庫  獲取數據庫操作句柄  這裏是關鍵  爲後續的對數據庫的操作提供保障
		RealProjectOpenHelper rpHelper  = new RealProjectOpenHelper(context, DB_NAME, null, VERSION);
		db = rpHelper.getWritableDatabase();
	}
	
	//線程安全的創建類實例
	public static RealProjectDB getInstance(Context context){
		if(realprojectDB == null) { //(1)  
	        //只有第一次才徹底執行這裏的代碼  
	       synchronized(RealProjectDB.class){  
	          //再檢查一次  
	          if(realprojectDB == null)  
	        	  realprojectDB = new RealProjectDB(context);  
	       }  
	    }  
	    return realprojectDB;    
	}
	
	/**
	 * 保存省份信息
	 * @param p
	 */
	public void saveProvince(Province p){
		if(p != null){
			ContentValues values = new ContentValues();
			values.put("province_name", p.getProvinceName());
			values.put("province_code", p.getProvinceCode());
			db.insert("Province", null, values);
		}
	}
	
	
	/**
	 * 獲取所有省份信息
	 * @return
	 */
	public List<Province> loadProvinces(){
		List<Province> list = new ArrayList<Province>();
		//查詢數據
		Cursor cursor = db.query("Province", null, null, null, null, null, null);
		if(cursor.moveToFirst()){
			do{
				Province p = new Province();
				p.setId(cursor.getInt(cursor.getColumnIndex("id")));
				p.setProvinceName(cursor.getString(cursor.getColumnIndex("province_name")));
				p.setProvinceCode(cursor.getString(cursor.getColumnIndex("province_code")));
				list.add(p);
			}while(cursor.moveToNext());
		}
		return list;
	}
	
	//還是保存城市鄉村信息和獲取城市鄉村信息   不再一一列出
}

2、有很多操作是需要訪問服務器獲取返回信息,此時就設計通用的類來做這件事情。

可以參考代碼如下:

/**
 * 與服務器交互類
 * @author Administrator
 *
 */
public class HttpUtil {
	
	/**
	 * 向服務器發送請求方法
	 * @param address
	 * @param listener
	 */
	public static void sendHttpRequest(final String address, final HttpCallbackListener listener){
		new Thread(new Runnable() {
			public void run() {
				HttpURLConnection connection = null;
				try{
					//建立連接
					URL url = new URL(address);
					connection = (HttpURLConnection)url.openConnection();
					connection.setRequestMethod("GET");
					connection.setConnectTimeout(8000);
					connection.setReadTimeout(8000);
					
					//獲取輸入流
					InputStream in = connection.getInputStream();
					BufferedReader reader = new BufferedReader(new InputStreamReader(in));
					
					//獲取返回的內容  通過StringBuilder進行拼接
					StringBuilder response = new StringBuilder();
					String line;
					while((line = reader.readLine()) != null){
						response.append(line);
					}
					
					if(listener != null){
						//回調onFinish方法
						listener.onFinish(response.toString());
					}
					
				}catch(Exception e){
					if(listener != null){
						//回調onError方法
						listener.onError(e);
					}
				}finally{
					connection.disconnect();
				}
				
			}
		}).start();
	}
}
這個方法中用到了一個接口參數,該接口很簡單:

/**
 * 回調接口
 * @author Administrator
 *
 */
public interface HttpCallbackListener {
	void onFinish(String response);
	void onError(Exception e);
}

個人理解:這個方法非常牛逼和通用,根據傳遞的地址獲取到服務器端返回的數據,然後調用接口中的方法,這個時候就非常的靈活了,因爲不同功能點對於該接口的實現方法不同,比如,在下面的應用中,可以如是調用代碼:

        //從服務器獲取數據
	private void queryFromServer(final String code, final String type){
		String address;
		if(!TextUtils.isEmpty(code)){
			address = "http://...."; //根據不同的code,設置不同的服務器地址
		}else{
			address = "";
		}
		
		//加載的時候,展示進度條
		showProgressDialog();
		
		//在此處確定地址,然後對於返回的數據編寫回調函數
		<span style="color:#ff0000;">HttpUtil.sendHttpRequest(address, new HttpCallbackListener() {</span>
			
			@Override
			<span style="color:#ff0000;">public void onFinish(String response)</span> {
				boolean result = false;
				if("province".equals(type)){
					result = Utility.handleProvinceResponse(db, response);
				}
				//去過是其他的,調用其他方法
				
				//如果返回數據處理成功
				if(result){
					<span style="color:#ff0000;">//回到主線程中
					runOnUiThread(new Runnable() {</span>
						@Override
						public void run() {
							closeProgressDialog();
							if("province".equals(type)){
								queryProvinces();
							}
							//如果是其他的,獲取城市或者縣城數據。
						}
					});
				}
			}
			
			@Override
			<span style="color:#ff0000;">public void onError(Exception e) {</span>
				runOnUiThread(new Runnable() {
					
					@Override
					public void run() {
						closeProgressDialog();
						Toast.makeText(ChooseAreaActivity.this, "加載失敗", Toast.LENGTH_SHORT).show();
					}
				});
			}
		});
	}


3、數據的存儲思路

如果是一些長期需要用到的數據,比如所有省份,城市信息等,那麼可以存到本地數據庫中,在獲取數據的時候先從本地數據庫獲取,如果沒有,那麼從服務器端獲取,對於返回的數據進行處理,處理的過程中存入到數據庫中。如果是一些臨時信息,思路是一樣的,但是可以先存儲在SharedPreferences中。


另外,還有一些變量用於判斷某些事情發生或者沒有發生,根據這些變量來做進一步的操作。此時也可以通過SharedPreferences來存儲。


4、如何實現定時任務?

可以在後臺啓動服務,然後通過定時器啓動接收器,在接收器中重新開啓服務,就是這種周而復始的搞下去。就達到了定時任務的效果。

在服務中,代碼核心如下:

public class AutoUpdateService extends Service {

	@Override
	public IBinder onBind(Intent arg0) {
		// TODO Auto-generated method stub
		return null;
	}
	
	public int onStartCommand(Intent intent, int flags, int startId){
		//開啓子線程調用定時任務
		new Thread(new Runnable() {
			@Override
			public void run() {
				doSomething();
			}
		}).start();
		
		//獲取廣播
		AlarmManager manager = (AlarmManager)getSystemService(ALARM_SERVICE);
		int anHour = 8 * 60 * 60 * 1000;
		long triggerAtTime = SystemClock.elapsedRealtime()+anHour;
		Intent i = new Intent(this,AutoUpdateReceiver.class);
		PendingIntent pi = PendingIntent.getBroadcast(this, 0, i, 0);
		manager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, triggerAtTime, pi);
		
		return super.onStartCommand(intent, flags, startId);
	}
	
	//定時操作
	public void doSomething(){}

}

接收器代碼如下:

public class AutoUpdateReceiver extends BroadcastReceiver {

	@Override
	public void onReceive(Context arg0, Intent arg1) {
		Intent i = new Intent(arg0,AutoUpdateService.class);
		arg0.startService(i);

	}

}







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