一些注意事项说明
(1) Bmob创建应用的 AppId可以和我们本地的应用不同哦,包名都不需要写,但是退送服务必须填写包名
MyUser user = BmobUser.getCurrentUser(this, MyUser.class);
该方法只需用户登陆成功后(只要不卸载应用),从内存中得到User对象(包含objectId,username,password等等)
(2)增删改查 原理其实都是根据 id 改变的(和 Sqlite,设置Hibernate其实是一样的)所以做这些操作时候一定要保证 id不为NULL
(3) 当一个用户的邮件被新添加或者修改过的话emailVerified会被默认设为false,如果应用设置中开启了邮箱认证功能,Bmob会对用户填写的邮箱发送一个链接,
这个链接可以把emailVerified设置为 true.
email还没有验证成功的情况下,用户或者邮箱 也可以登录成功,仅仅emailVerified为false而已
(4)BmobQuery 查询单条数据使用
query.getObject(context, objectId, callback)
BmobQuery 查询 多条数据使用
query.findObjects(this, new FindListener
(5)User bmobUser = (User) User.getCurrentUser(this);抛出错误,不能转换,看来本地缓存对象只保存了 BmobUser
数据库操作(查询)
查询单条数据
BmobQuery query = new BmobQuery();
query.getObject(this, "b343b9d4f7", new GetListener() {
@Override
public void onFailure(int code, String reason) {
Toast.makeText(MainActivity.this, "code"+code +" "+reason, Toast.LENGTH_SHORT).show();
}
@Override
public void onSuccess(MyUser user) {
Toast.makeText(MainActivity.this, user.getUsername(), Toast.LENGTH_SHORT).show();
}
});
查询多条数据
BmobQuery query = new BmobQuery();
query.findObjects(this, new FindListener() {
@Override
public void onSuccess(List list) {
Toast.makeText(MainActivity.this, "得到的用户数是:"+list.size(), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(int code, String msg) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "code"+code +" "+msg, Toast.LENGTH_SHORT).show();
}
});
注意 :
query.getObject(this, "b343b9d4f7", new GetCallback()
//查询单条
query.findObjects(this, new FindCallback() {}
//查询多条
这 两个回调函数什么也查不到,故不要使用。
官方说: 应该在使用 自定义表名 的情况下使用上面两个方法(上面两个回调返回的参数是Json格式的,需要自己解析)
数据库操作(更新)
(1)需要用户先登录成功
(2)MyUser user = BmobUser.getCurrentUser(this,MyUser.class);
MyUser myuser = BmobUser.getCurrentUser(this, MyUser.class);
myuser.setNickName("稻草人2");
myuser.setAddress("北京市");
myuser.update(this, new UpdateListener() {
@Override
public void onSuccess() {
// TODO Auto-generated method stub
toast("更新用户信息成功");
}
@Override
public void onFailure(int arg0, String arg1) {
// TODO Auto-generated method stub
}
});
登录功能
只需要 开启邮箱验证,或者手机验证等等,那么user.setUsername(user) user 就可以填写邮箱号码或手机号充当username。
MyUser user = new MyUser();
user.setUsername("可填用户名或者邮箱号"); //开启邮箱验证的情况下
user.setPassword("abc");
user.setEmail("这里可填可不填");
user.login(this, new SaveListener() {
@Override
public void onSuccess() {
Toast.makeText(MainActivity.this, "登录成功", Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int arg0, String arg1) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "登录失败:"+arg1, Toast.LENGTH_SHORT).show();
}
});
重置密码(该方法直接发送更新密码的邮件,不需要登陆用户就可以使用)
因为如果用户真的使用 xx邮箱注册过,那么他就可以直接登陆xx邮箱 修改 密码,这是安全的做法,请放心使用
final String email = "[email protected]";
BmobUser.resetPasswordByEmail(this, email, new ResetPasswordByEmailListener() {
@Override
public void onSuccess() {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this,"重置密码请求成功,请到" + email + "邮箱进行密码重置操作",Toast.LENGTH_SHORT).show();
}
@Override
public void onFailure(int arg0, String arg1) {
// TODO Auto-generated method stub
}
});
等价关系
MyUser user = BmobUser.getCurrentUser(this, MyUser.class);
user.setValue("age", "10000");
等价于
user.setAge("10000");
注意: user.setAge(null); 和user.setValue("age",null);
测试对数据无效,故删除age字段数据使用user.setAge(""); 或者 user.remove("age");
user.update(this);
保存对象和数组的功能
MyUser user = BmobUser.getCurrentUser(this,MyUser.class);
List hobbys = new ArrayList();
hobbys.add("阅读");
hobbys.add("篮球");
hobbys.add("唱歌");
user.setHobbys(hobbys);
BankCard bankCard = new BankCard();
bankCard.setTitle("中南银行");
user.setBankCard(bankCard); //等价user.setValue("bankCard",bankCard);
user.update(this);
查看云端 数据 发现 存储形式是:
hobbys(Array) ["阅读","篮球","唱歌"]
bankCard(Object) {"title":"中南银行"} 对象以 json格式存储
删除hobbys中的数据
删除user用户的hobby属性中含有 阅读","唱歌","游泳的 字符串
user.removeAll("hobby", Arrays.asList("阅读","唱歌","游泳"));
成功删除阅读,游泳(唱歌在云端原本不存在哦)
user.update(this, new UpdateListener() {
.....
}
数组 数据的添加
对于数组类型数据, add addAll (在一个数组字段的后面添加一些指定的对象(包装在一个数组内)
如 : user.add("hobbys","泡妞"); user.update(this);
更新之后 云端数据是: ["篮球","唱歌","泡妞"]
如 : user.addAll("hobbys", Arrays.asList("打架", "斗殴"));
云端数据 : ["篮球","唱歌","泡妞","打架","斗殴"]
当然了: 数组里面不仅可以放String类型,也可以放Object类型哦
如: user.add("hobbys",new XingQu("泡妞"));
addUnique、addAllUnique(只会在原本数组字段中没有这些对象的情形下才会添加入数组,插入数组的位置随机)
删除数组数据 ,同理我们也可以使用removeAll从数组字段中移除某些值:
Person p = new Person();
p.removeAll("hobby", Arrays.asList("阅读","唱歌","游泳"));
p.update(this, new UpdateListener() {
.......
}
查询数组数据
BmobQuery query = new BmobQuery();
String [] hobby = {"阅读","唱歌"};
query.addWhereContainsAll("hobby", Arrays.asList(hobby));
query.findObjects(this, new FindListener() {
...
}
分页查询
query.setLimit(10); // 限制最多10条数据结果作为一页
query.setSkip(10); // 忽略前10条数据(即第一页数据结果)
类似 mysql 的limit
排序
// 根据score字段升序显示数据
query.order("score");
// 根据score字段降序显示数据
query.order("-score");
// 多个排序字段可以用(,)号分隔
query.order("-score,createdAt");
说明:多个字段排序时,先按第一个字段进行排序,再按第二个字段进行排序,依次进行。
批量操作
注意:
1.任何一种批量操作每次只支持最大50条记录的操作。
2.批量操作不支持对User表的操作。
new BmobObject().insertBatch
new BmobObject().updateBatch
new BmobObject().deleteBatch
批量上传
Bmob.uploadBatch(context, filePaths, new UploadBatchListener() {
BmobProFile.getInstance(context).uploadBatch(files, new UploadBatchListener() {....}
关联关系(关联关系映射)
问题代码 (下面成功创建两张表,且创建了关联关系,但是 user.setDepartment(department);失败,因为本地对象还没有赋值objectId)
结果:
User表
objectId name department Pointer
8cb0fd1660 "经理部" null
错误代码如下
Department department = new Department();
department.setName("网购部门");
department.save(this);
User user = new User();
user.setName("xx");
user.setAge("20");
user.setDepartment(department);
user.save(this);
注:include的查询对象只能为BmobPointer类型,而不能是BmobRelation类型。
一对一
知道一个Department depart,查询该 depar下所有的User(User方设置外键 )
Bmob的做法:
Department depart = findDepartmentById(d9330d061c);
BmobQuery query = new BmobQuery();
query.addWhereEqualTo("depart",depart); //
query.include("depart"); //查询得到的Users里面含有 depart(外键属性)
query.findObjects(this,new FindListener(){.......} );
总结: 上面的方式就如同
Hibernate中 Department表
Set users = new HashSetusers();
Department depart = findDepartmentById(d9330d061c);
depart.getUsers();
一对多
查询评论(很像上面查询 用户)
//Conmment评论 ,Post帖子,User用户
Post post = findDepartmentById(1ffegca); //这个对象只需要 objectId即可
BmobQuery query = new BmobQuery();
query.addWhereEqualTo("post",new BmobPointer(post));
//希望同时查询该评论的发布者的信息,以及该帖子的作者的信息,这里用到上面`include`的并列对象查询和 内嵌对象的查询
query.include("user,post.author");
query.findObjects(this, new FindListener(){....}
知道了一个User user,查询 该User对应的Department
User user = findById(0ffg034);
BmobQuery query = new BmobQuery();
query.include("depart");
query.getObject(); //query.findObjects(); 和 [知道一个Department depart,查询该 depar下所有的User]用法完全一样,仅仅addWhereEqualTo不一样而已啦
多对多关系
一个帖子可以被很多用户所喜欢,一个用户也可能会喜欢很多帖子,那么可以使用Relation类型来表示这种多对多关联关系。
Relation本质上可以理解为其存储的是一个对象,而这个对象中存储的是多个指向其它记录的指针。(中间关系表 )
内部查询
非常类似于 mysql中的 子查询
如: 查询带有图片的帖子的评论列表:
mysql的做法是
1.先查询所有带图片的帖子
2.从这些帖子里面查询所有评论)
BmobQuery query = new BmobQuery();
BmobQuery innerQuery = new BmobQuery();
innerQuery.addWhereExists("image", true);
// 第一个参数为评论表中的帖子字段名post(我理解为外键名)
// 第二个参数为Post字段的表名,也可以直接用"Post"字符串的形式(我理解为One方的表名)
// 第三个参数为内部查询条件
query.addWhereMatchesQuery("post", "Post", innerQuery);//反之,不想匹配某个子查询,你可以使用addWhereDoesNotMatchQuery方法(查询不带图片的帖子的评论列表)
query.findObjects(this, new FindListener() {
@Override
public void onSuccess(List object) {
// TODO Auto-generated method stub
toast("查询成功:");
}
@Override
public void onError(int code, String msg) {
// TODO Auto-generated method stub
toast("查询失败:"+msg);
}
});
内部查询实例2:
BmobQuery userQuery = new BmobQuery();
BmobQuery innerQuery = new BmobQuery();
innerQuery.addWhereEqualTo("name", "经理部");
userQuery.addWhereMatchesQuery("department", "Department", innerQuery);
userQuery.findObjects(this, new FindListener() {
@Override
public void onSuccess(List arg0) {
Toast.makeText(MainActivity.this, "查询成功"+arg0.size(), Toast.LENGTH_SHORT).show();
}
@Override
public void onError(int arg0, String arg1) {
// TODO Auto-generated method stub
Toast.makeText(MainActivity.this, "查询失败", Toast.LENGTH_SHORT).show();
}
});
文件上传操作
文件上传操作:
先上传文件,上传成功后,像普通对象一样,再进行数据的添加操作。
insertObject(new MyUser("wangli",bmobFile));
注意: MyUser表结构是 String | BmobFile类型
BmobFile icon = bmobFile.getIcon();
icon.loadImage(TestFileActivity.this, iv_icon);// iv_icon是ImageView
BmobFile icon = bmobFile.getIcon();
icon.loadImageThumbnail(TestFileActivity.this, iv_icon, 100, 100, 100); //iv_icon是ImageView
文件操作详解
旧版 BmobFile 文件下载的具体代码实现需要大家自行实现
新版 BmobProFile文件下载已经实现
虽然新版上传下载更好,但是 云端字段最好还是设置成 BmobFile类型的;
如 User表 name(String) icon(BmobFile)
新版: 文件的单一上传、批量上传、文件下载、生成缩略图等功能。
单一上传
BmobProFile.getInstance(context).upload(filePath, new UploadListener() {
@Override
public void onSuccess(String fileName,String url,BmobFile file) {
Log.i("bmob","文件上传成功:"+fileName+",可访问的文件地址:"+file.getUrl());
// TODO Auto-generated method stub
// fileName :文件名(带后缀),这个文件名是唯一的,开发者需要记录下该文件名,方便后续下载或者进行缩略图的处理
// url :文件地址
// file :BmobFile文件类型,`V3.4.1版本`开始提供,用于兼容新旧文件服务。
注:若上传的是图片,url地址并不能直接在浏览器查看(会出现404错误),需要经过`URL签名`得到真正的可访问的URL地址,当然,`V3.4.1`的版本可直接从'file.getUrl()'中获得可访问的文件地址。
}
}
批量上传 :BmobProFile.getInstance(context).uploadBatch(files, new UploadBatchListener() {}
文件下载: BmobProFile.getInstance(context).download(fileName, new DownloadListener() {}//这个filename参数是 使用BmobProFile上传成功的 fileName,自行保存
获取文件地址: BmobProFile.getInstance(context).getAccessURL(fileName, new GetAccessUrlListener() {} //fileName也是 BmobProFile上传成功的fileName
文件删除:BmobProFile.getInstance(context).deleteFile(fileName, new DeleteFileListener() {}//fileName也是 BmobProFile上传成功的fileName
缓存目录:(里面存储了BmobProFile下载下来的文件)
1.可以自定义缓存目录名称,可在Apllication中对其进行初始化配置(下载文件前调用哦)
BmobConfiguration config = new BmobConfiguration.Builder(context).customExternalCacheDir("目录名").build();
BmobPro.getInstance(context).initConfig(config);
2.注意事项
(1)缓存总目录下,包含上面两个分目录,分别用于保存下载文件和缩略图(这个缩略图我们都不需要,自己写算了)。
(2)因为Android手机系统的高定制度和复杂性,此方法只允许定义缓存目录的名称,并不支持自定义缓存路径,缓存路径由SDK根据手机系统进行分配。
(3)获取各分目录的完整路径:
通过如下方法可获取保存下载文件的完整路径:
//可自行打印此路径,通过文件管理器查看文件是否下载成功
BmobPro.getInstance(context).getCacheDownloadDir()
(4)获取缓存大小:
//文件大小(单位:字节)
String cacheSize = String.valueOf(BmobPro.getInstance(context).getCacheFileSize());
//对文件大小进行格式化,转化为'B'、'K'、'M'、'G'等单位
String formatSize = BmobPro.getInstance(context).getCacheFormatSize();
(5)清除缓存:
BmobPro.getInstance(context).clearCache();