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);

	}

}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值