xutils简介:
xUtils 是一个工具类的集合体,其中包含许多实用的Android工具,主要包含四大模块:
2、 DBUtils的模块
3、
HttpUtils的模块
4、
BitmapUtils的模块
xUitls最低兼容Android 2.2 (API 8)
下载地址:
https://github.com/wyouflf/xUtils,目前的版本是2.6.14
xutils3目前还不太稳定,不建议使用
ViewUtils:
java反射(Reflect)和注解(
Annotation)的使用
反射:
在运行时状态,
对于任意一个类,知道这个类的属性和方法,
对于任意一个对象,访问它的任意一个属性和方法
动态获取类或者对象的信息以及动态调用对象方法
public class ReflectTest {
/**
* 使用反射调用公有方法,getMethod获取公有方法,类名要包含完整包名
* @return
*/
static int getAgeByReflectMethod(){
int age = 0;
try {
Class cls = Class.forName("com.qianfeng.zhouyi.xutilstest.Student");
Object obj = cls.newInstance();
Method setAgeMethod = cls.getMethod("setAge", int.class);
setAgeMethod.invoke(obj,10);
Method getAgeMethod = cls.getMethod("getAge");
age = (int) getAgeMethod.invoke(obj);
} catch (Exception e) {
Log.d("LessonXutils",e.getMessage());
}
return age;
}
/**使用反射访问私用属性,getDeclaredField能获取私有或公有属性,要调用setAccessible使其可以访问
*
* @return
*/
static int getAgeByReflectField(){
int age = 0;
try {
Class cls = Class.forName("com.qianfeng.zhouyi.xutilstest.Student");
Object obj = cls.newInstance();
Field fd = cls.getDeclaredField("age");
fd.setAccessible(true);
fd.set(obj,10);
age = (int) fd.get(obj);
} catch (Exception e) {
Log.d("LessonXutils",e.getMessage());
}
return age;
}
/**调用私有静态方法,getDeclaredMethod可以获取私有或公有方法,要调用setAccessible使其可以访问
* 静态方法不用newInstance得到对象
*
*/
static void invokeStaticMethod(){
try {
Class cls = Class.forName("com.qianfeng.zhouyi.xutilstest.Student");
Method staitcMethod = cls.getDeclaredMethod("test");
staitcMethod.setAccessible(true);
staitcMethod.invoke(cls);
} catch (Exception e) {
Log.d("LessonXutils", e.getMessage());
}
}
}
class Student{
private int age;
private String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private static void test(){
Log.d("LessonXutils","invoke test by reflect");
}
}
注解(Annotation):
- 基本注解:
- 元注解
修饰注解的注解,用于自定义注解
@Retention 表示在什么级别保存该注解
RetentionPolicy.SOURCE - 对源代码有效,编译后丢弃
RetentionPolicy.CLASS - 对class文件有效,运行时丢弃
RetentionPolicy.RUNTIME - 内存中的字节码,在VM在运行时保留注解,才能够通过反射获取注解信息@Target - 表示注解用在什么位置
ElementType.FIELD - 用在成员变量,用在枚举属性
ElementType.METHOD - 用在方法上
ElementType.TYPE - 类或者接口,或者枚举
ElementType.PACKAGE - 用在包上
ElementType.LOCAL_VARIABLE - 局部变量
ElementType.PARAMETER - 参数上
- 自定义注解的实现和使用
定义一个注解
自定义一个注解,需要先使用元注解来声明注解的保留级别和应用位置
注解中可以包含属性,跟普通属性不一样,它类似于接口中的方法,可以设置默认值返回值
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyAnnotation {
int value() default 10;
String name() default "Ann";
}
使用注解给属性赋值:
public class AnnotationTest {
//使用注解
@MyAnnotiaon(name="age",value = 12)
private int age;
//使用注入方式赋值
public static void inject(AnnotationTest test){
Class cls = AnnotationTest.class;
try {
Field field = cls.getDeclaredField("age");
field.setAccessible(true);
//可以直接赋值
//field.set(test,10);
//得到这个属性的注解,然后获取注解里的value,用这个value设置属性值
MyAnnotiaon ann = field.getAnnotation(MyAnnotiaon.class);
int iAge = ann.value();
field.set(test,iAge);
} catch (Exception e) {
e.printStackTrace();
}
}
public int getAge(){
return age;
}
}
Android中的ioc框架,完全注解方式就可以进行UI、资源和事件注入绑定
控制反转(Inversion of Control,英文缩写为 IoC):创建被调用者的工作不再由调用者来完成,因此称为控制反转。
使用注解和反射来实现控制反转(注入)
调用ViewUtils.inject(this),此方法中会利用反射遍历类中所有注解,对注解的功能一一实现
- activity中Contentview的注解
@ContentView(value = R.layout.activity_main)
- activity中View控件的注解
@ViewInject(R.id.btTest)
private Button mBtnTest;
- activity中资源文件的注解
@ResInject(type = ResType.String,id = R.string.app_name)
String strAppName;
- activity中事件的注解
@OnClick(R.id.btTest)
public void onClick(View view){
Toast.makeText(this,"onClick",Toast.LENGTH_SHORT).show();
}
- fragment中的使用:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
// 加载布局
View view = inflater.inflate(R.layout.db_fragment, container, false);
// 依赖注入,第一个是用来反射获取注解,第二个参数用来findviewbyid
ViewUtils.inject(this, view);
return view;
}
@ViewInject(R.id.db_test_btn)
private Button stopBtn;
@ViewInject(R.id.result_txt)
private TextView resultText;
@OnClick(R.id.db_test_btn)
public void testDb(View view) {
}
- BaseAdapter中的使用
protected class ViewHolder {
@ViewInject(R.id.tvItem)
public TextView tvItem;
}
注入的时候需要传2个参数,第一个是注解所在的类,为了获取注解,第二个是父view,为了调用findviewbyid得到注解所标记的view
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = layoutInflater.inflate(R.layout.layout_listitem, null);
ViewHolder viewHolder = new ViewHolder();
//viewHolder.tvItem = (TextView) convertView.findViewById(R.id.tvItem);
ViewUtils.inject(viewHolder,convertView);
convertView.setTag(viewHolder);
}
initializeViews((T)getItem(position), (ViewHolder) convertView.getTag());
return convertView;
}
@OnItemClick(R.id.lvTest)
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(this,"onItemClick",Toast.LENGTH_SHORT).show();
}
- 需要添加访问存储卡的权限
- 定义数据表对应的类,必须是public的非内部类(单独一个类文件)
//指定表名,如果不用这个注解,表名默认为包名+类名
@Table(name="tbl_User")
public class User {
//主键,必须有,自增长
@Id
private int id;
//指定列名,如果不指定,就是字段名
//Unique注解代表字段唯一,不重复
@Column(column="username")
@Unique
private String name;
//column可以省略
//非空
@Column
@NotNull
private String email;
//规定年龄值的范围
@Check("20 <= age and age <= 130")
private int age;
//getxxx
//setxxx
//tostring
//......
常见的DB注解:
@Check check约束
@ Column 列名
@ Id 主键,一般设置为int,自增长
@ Column 列名
@ Id 主键,一般设置为int,自增长
@
NotNull 不为空
@ Table 表名
@ Unique 唯一约束
@ Table 表名
@ Unique 唯一约束
- 创建数据库(指定路径时需要加入写文件权限)
/**
* 创建数据库,默认路径:/data/data/包名/database/xutils.db
*/
protected void createDb(){
mdbUtils = DbUtils.create(this);
}
/**
* 创建数据库,指定路径和数据库名
*/
protected void createDbWithDirName(){
String strPath = "/sdcard/";
Log.d("createDbWithDirName", "path=" + strPath);
mdbUtils = DbUtils.create(this, strPath, "mydb2");
}
/**
* 使用配置方式创建数据库
*/
protected void createDbWithConfig(){
DbUtils.DaoConfig daoConfig = new DbUtils.DaoConfig(this);
daoConfig.setDbDir("/sdcard/");
daoConfig.setDbName("mydb");
mdbUtils = DbUtils.create(daoConfig);
}
- 创建数据表并插入数据
protected void createTableAndInsert(){
User user = new User();
user.setName("zhangsan");
user.setEmail("zhangsna@1000phone.com");
user.setAge(20);
User user2 = new User();
user2.setName("lisi");
user2.setEmail("lisi@1000phone.com");
user2.setAge(22);
List<User> listusers = new ArrayList<User>();
listusers.add(user);
listusers.add(user2);
try {
mdbUtils.saveAll(listusers);
} catch (DbException e) {
Log.d("LessonDbUtils",e.getMessage());
}
}
- 查询数据
查询所有数据:
protected void queryData(){
try {
List<User> listUsers = mdbUtils.findAll(User.class);
Log.d("queryData", listUsers.toString());
} catch (DbException e) {
e.printStackTrace();
}
}
条件查询:
protected void query() {
try {
List<User> users = dbUtils.findAll(com.lidroid.xutils.db.sqlite.Selector.from(User.class)
.where("age", "=", "29")
.or("age","=","28")
);
Log.d("qf", users.toString());
} catch (Exception e) {
Log.e("qf", e.toString());
}
}
sql语句查询:
protected void query() {
List<User> listUsers = new ArrayList<>();}
Cursor cursor = MyApplication.mDbUtils.execQuery("select * from tbl_user");
int iNameIndex = cursor.getColumnIndex("username");
int iEmailIndex = cursor.getColumnIndex("email");
int iAgeIndex = cursor.getColumnIndex("age");
int iIdIndex = cursor.getColumnIndex("id");
while (cursor.moveToNext()){
User user = new User();
String strUserName = cursor.getString(iNameIndex);
String strEmail = cursor.getString(iEmailIndex);
int iAge = cursor.getInt(iAgeIndex);
int iId = cursor.getInt(iIdIndex);
user.setAge(iAge);
user.setEmail(strEmail);
user.setName(strUserName);
user.setId(iId);
listUsers.add(user);
}
cursor.close();
Log.d("qf",listUsers.toString());
} catch (DbException e) {
e.printStackTrace();
Log.e("qf",e.getMessage());
}
- 更新数据
更新单条数据:
protected void updateData(){
try {
User user = mdbUtils.findById(User.class, 2);
user.setAge(32);
mdbUtils.update(user, "age");
} catch (DbException e) {
e.printStackTrace();
}
}
按条件更新:
protected void update(){
try {
User user = new User();
user.setAge(40);
dbUtils.update(user, WhereBuilder.b("id",">","0"),"age");
} catch (DbException e) {
Log.e("qf", e.toString());
}
}
批量更新数据,对象中必须设置id,以id为索引,更新指定列的值
protected void update(){
try {
User user = new User();
user.setId(1);
user.setAge(30);
User user1 = new User();
user1.setId(2);
user1.setAge(30);
List<User> users = new ArrayList<>();
users.add(user);
users.add(user1);
dbUtils.updateAll(users,"age");
} catch (DbException e) {
Log.e("qf", e.toString());
}
}
sql语句更新数据:
protected void update(){
try {
dbUtils.execNonQuery("update table_user set age = 35 where id = 1");
} catch (DbException e) {
Log.e("qf", e.toString());
}
}
- 删除数据
protected void deleteData(){
User user = new User();
user.setId(2);
try {
mdbUtils.delete(user);
} catch (DbException e) {
e.printStackTrace();
}
}
练习——72g手游助手,选一个页面,对网络数据在数据库中做缓存,打开界面的时候,如果判断没有网络,把缓存在数据库中的内容显示出来
判断网络是否连接好:
// 检测网络
public static boolean checkNetworkAvailable(Context context) {
ConnectivityManager connectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
if (connectivity == null) {
return false;
} else {
NetworkInfo[] info = connectivity.getAllNetworkInfo();
if (info != null) {
for (int i = 0; i < info.length; i++) {
if (info[i].getState() == NetworkInfo.State.CONNECTED) {
NetworkInfo netWorkInfo = info[i];
if (netWorkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
return true;
} else if (netWorkInfo.getType() == ConnectivityManager.TYPE_MOBILE) {
return true;
}
}
}
}
}
return false;
}
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>