当前位置: 代码迷 >> Android >> Active Android的一些见解与研究
  详细解决方案

Active Android的一些见解与研究

热度:22   发布时间:2016-05-01 16:27:46.0
【原创】Active Android的一些见解与研究
这几天一直在找一个针对android数据库sqlite的一个orm框架,起初找了一个google上面的项目:android active record,无奈,demo可以运行,但自己写了一个应用,却怎么也跑不起来,原因是创建DB的sql语句有错误。于是debug了一番,然后发现错误不仅仅是这些。要我改原作者的代码是不可能的,更何况他的代码还没有完善与健壮。尔后几天一直在找有没有相应的框架可替代。找了个ormlite和sqlitegen,都不竟如人意,并不是说它们的框架设计得不合理,而是就简约和敏捷开发而言。orm的缺点就暴露了出来,令外,手机软件一般追求的是代码简洁,而J2EE的这一套显然在这里无法适用。终于,被我找到了一个商业版的active android。思想跟我找到那个google项目一样,都是基于RoR的activeRecord模式设计的。我下了一个试用版(正式版可要付$19.99 T_T)。再反编译一下,天,居然没有代码混淆。于是,看了下代码的实现。研究了大概1天半的时间。它的实例也跑过了,再把它应用于自己的小例子中,终于,跨过重重的困难。勉强OK了。但这里有个问题摆在眼前,试用版的,一些功能会有限制,果然,在它代码里面,我看到了它仅限于运行在模拟器。而且生成的DB名字不可变更。DB命名的那段逻辑在它自己实现的application上面call。且这些代码封装在它的jar包里面。这样就意味着application的命名要跟jar包里面的一致,否则无法应用。看来,要改它的代码是必然的,不然这些限制将不利于自己的应用(在这里,希望一些版权人士不要喷我,小弟只是抱着学习的态度去研究这框架,并未用于商业的开发)。于是,经过昨天的熬夜奋战,终于解决了这一问题,改了它的实现接口,在应用端方法只需写一个类继承那个jar包的application就可以了。另外,运行于真机器也没问题。好了,不多说了,上一个我的小例子ActiveAndriodDemo,方便大家理解。
1.AndroidManifest.xml上面的改动。
<application android:icon="@drawable/icon" android:label="@string/app_name" android:name="com.kevin.PersonApp">...</application>

2.创建一个跟上面命名一样的PersonApp类,并继承activeAndroid.jar下面的applicatiion类。
package com.kevin;import com.activeandroid.Application;public class PersonApp extends Application {	public PersonApp() {                  //naming DB name and DB version		                  super("PersonApp.db", 1);	}}


3.domain类(Person.java)
package com.kevin.entity;import java.util.List;import android.content.Context;import com.activeandroid.ActiveRecordBase;import com.activeandroid.annotation.Column;import com.activeandroid.annotation.Table;@Table(name = "Person")             //naming table namepublic class Person extends ActiveRecordBase<Person>{	public Person(Context context) {		super(context);	}	         //naming column name, just ignore length value setting         @Column(name = "Name")	public String name;	@Column(name = "age")	public String age;		public static List<Person> getAll(Context context) {		return Person.query(context, Person.class, null, null, null);	}}

4.创建一个适配器PeopleAdapter.java
package com.kevin.adapter;import java.util.ArrayList;import java.util.List;import com.kevin.R;import com.kevin.entity.Person;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.TextView;public class PeopleAdapter extends BaseAdapter {	private LayoutInflater layoutInflater;	private List<Person> people = new ArrayList<Person>();		public PeopleAdapter(Context context, List<Person> personList) {		layoutInflater = LayoutInflater.from(context);		people.addAll(personList);	}	@Override	public int getCount() {		return people.size();	}	@Override	public Object getItem(int position) {		return people.get(position);	}	@Override	public long getItemId(int position) {		return people.get(position).getId();	}	@Override	public View getView(int position, View convertView, ViewGroup parent) {		ViewHolder holder = new ViewHolder();		Person person = (Person) getItem(position);		if (convertView == null) {			convertView = layoutInflater.inflate(R.layout.list_item, null);			holder.id = (TextView) convertView.findViewById(R.id.p_id);			holder.name = (TextView) convertView.findViewById(R.id.p_name);			holder.age = (TextView) convertView.findViewById(R.id.p_age);			convertView.setTag(holder);		} else {			holder = (ViewHolder) convertView.getTag();		}		holder.id.setText(person.getId() + "");		holder.name.setText(person.name);		holder.age.setText(person.age);		return convertView;	}		class ViewHolder{		TextView id;		TextView name;		TextView age;	}}

5.Main.java主activity
package com.kevin;import java.util.List;import com.kevin.adapter.PeopleAdapter;import com.kevin.entity.Person;import android.app.AlertDialog;import android.app.Dialog;import android.app.ListActivity;import android.content.DialogInterface;import android.os.Bundle;import android.view.ContextMenu;import android.view.LayoutInflater;import android.view.Menu;import android.view.MenuInflater;import android.view.ContextMenu.ContextMenuInfo;import android.view.MenuItem;import android.view.View;import android.widget.EditText;import android.widget.AdapterView.AdapterContextMenuInfo;public class Main extends ListActivity {		private PeopleAdapter peopleAdapter;	private static final int EDIT_DIALOG = 1;	private static final int ADD_MENU = 0;	private EditText editName;	private EditText editAge;	private Person person;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        loadList();        registerForContextMenu(getListView());    }	@Override	public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {		super.onCreateContextMenu(menu, v, menuInfo);		MenuInflater inflater = getMenuInflater();		inflater.inflate(R.menu.item_menu, menu);	}	@Override	public boolean onContextItemSelected(MenuItem item) {		AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();		switch (item.getItemId()) {		case R.id.edit: {			editPerson(info.id);			return true;		}		case R.id.delete: {			deletePerson(info.id);			return true;		}		default:			return super.onContextItemSelected(item);		}	}	@Override	public boolean onCreateOptionsMenu(Menu menu) {		menu.add(0, ADD_MENU, 0, "Add Person");		return true;	}	@Override	public boolean onMenuItemSelected(int featureId, MenuItem item) {		switch (item.getItemId()) {		case ADD_MENU:			addPerson();			return true;		default:			return super.onMenuItemSelected(featureId, item);		}	}	@Override	protected Dialog onCreateDialog(int id) {		switch (id) {		case EDIT_DIALOG: {			LayoutInflater inflater = LayoutInflater.from(this);			View textEntryView = inflater.inflate(R.layout.alert_dialog, null);			editName = (EditText) textEntryView.findViewById(R.id.name);			editAge = (EditText) textEntryView.findViewById(R.id.age);			AlertDialog.Builder builder = new AlertDialog.Builder(Main.this);			builder.setView(textEntryView);			String title = "Add Person";			if (person != null) {				title = "Edit Person";				editName.setText(person.name);				editAge.setText(person.age);			}			builder.setTitle(title);						builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {								@Override				public void onClick(DialogInterface dialog, int which) {					String name = editName.getText().toString();					String age = editAge.getText().toString();					if(person == null) {						person = new Person(Main.this);					}					person.name = name;					person.age = age;					person.save();					loadList();					removeDialog(EDIT_DIALOG);				}			});			builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {				@Override				public void onClick(DialogInterface dialog, int which) {					removeDialog(EDIT_DIALOG);				}			});			return builder.create();		}		default:			return super.onCreateDialog(id);		}	}		private void loadList() {		List<Person> personList = Person.getAll(this);		peopleAdapter = new PeopleAdapter(this, personList);		setListAdapter(peopleAdapter);	}		private void editPerson(long id) {		person = Person.load(this, Person.class, id);		showDialog(EDIT_DIALOG);	}		private void deletePerson(long id) {		Person.delete(this, Person.class, id);		loadList();	}		private void addPerson() {		person = null;		showDialog(EDIT_DIALOG);	}}

由于例子较长,部分代码(渲染界面和menu)忽略。
在这里总结一下ActiveAndroid。
优点:  方便,不用写sql,领域驱动模式可以使CRUD封装到domain上面,还可以扩展条件查询,支持简单的外键功能。
缺点:  每个表都默认有Id字段,并且是自增长,不可以自定义主键。不适应于小项目,性能较差。annotation的信息较小,生成的DDL十分的笼统。
修改:可以应用于真机器上面。可自定义数据库名或版本名,并且可自定义application name。

还有个小技巧可以教大家:
android 项目引入lib
1.在project上面添加"libs"
2.将library copy到libs下面
3.将library右键添加入项目
这样,lib会随着project一起安装。
   
  相关解决方案