书小白书单功能实现
文章目录
Bookxiaobai 书小白书单
书小白书单是个保存书单的小应用。
主要功能是通过搜索书名或者通过扫描书本的isbn号来获取书籍信息,并将书籍收入清单中。
并可通过设置书本状态,设置已读未读。以timeline的形式形成自己的读书清单列表。
其中书本的信息主要访问的是豆瓣的API
代码地址:https://github.com/lynn8570/BookXiaobai
主要的功能实现介绍
采用mockplus初步的原型设计
Mokcplus是一个非常简单好用的原型设计工具,官网上有一些简易的视频教程,看看几本就会一些几本的功能。不管会不会,撸起袖子加油干,试试,就会了。
按照几本功能设计的原型大改如下图,细节与最后的实现略有差别
主要包括主页面采用timeline的形式显示收藏的书单列表,顶部为搜索框,右边为条形码扫描按钮。
扫描图书二维码获取isbn号
ZXing (“zebra crossing”) is an open-source, multi-format 1D/2D barcode image processing
library implemented in Java, with ports to other languages.
直接使用zxing库来实现条码的扫描,源码地址:zxing github地址
添加依赖
1
2compile 'com.google.zxing:core:3.3.2'
compile 'com.journeyapps:zxing-android-embedded:3.5.0'启用内置的activity进行条码扫描
1
2
3
4
5
6imageViewScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new IntentIntegrator(MainActivity.this).initiateScan();
}
});在onClick的时候,启动并初始化扫描页面
在onActivityResult中获取扫描结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
if (result != null) {
if (result.getContents() == null) {
Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show();
} else {
Toast.makeText(this, "Scanned: " + result.getContents(), Toast.LENGTH_LONG).show();
String strIsbn = result.getContents();//得到isbn号
if (!TextUtils.isEmpty(strIsbn)) {
mBookPresenter.getBookByIsbn(strIsbn);
}
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
通过isbn号查询豆瓣API获取图书信息
豆瓣根据isbn号获取图书的API接口:api地址
例如通过访问 https://api.douban.com/v2/book/isbn/9787115412744
即可获取图书信息
- 采用MVP的结构,我们可以从接口获取到的json信息直接生成model中的BookBean类:具体方式可搜索插件GsonFormat自动生成javabean
- 使用restrofit封装几个需要用到的豆瓣图书API:通过isbn号获取图书信息,通过图书ID获取图书信息。
采用object box保持本地数据
Objectbox is designed for mobile. It is an object-oriented embedded database and a full alternative for SQLite. ObjectBox is incidentally also well-suited for IoT.
具体介绍可查看官网。
添加依赖
1
2
3
4
5
6
7apply plugin: 'io.objectbox'
....
....
android{
//add object box
compile "io.objectbox:objectbox-android:1.4.0"
}初始化,在application 的onCreate中进行初始化
1
2
3
4
5BoxConfig.boxStore = MyObjectBox.builder().androidContext(app).build();
Log.i(TAG,"init()............boxstore="+boxStore);
if (BuildConfig.DEBUG) {
new AndroidObjectBrowser(boxStore).start(app);
}对象注释
ObjectBox跟其他的ORM框架一样,通过对象属性注解来决定是否要持久化某个对象,或者某个属性。
@Entity:这个对象需要持久化。
@Id:这个对象的主键。
@Index:这个对象中的索引。对经常大量进行查询的字段创建索引,会提高你的查询性能。
@NameInDb:有的时候数据库中的字段跟你的对象字段不匹配的时候,可以使用此注解。
@Transient:如果你有某个字段不想被持久化,可以使用此注解。
@Relation:做一对多,多对一的注解
基础操作,增删改查
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
package com.lynn.bookxiaobai.boxstore.base;
import com.lynn.bookxiaobai.boxstore.BoxConfig;
import java.util.List;
import io.objectbox.Box;
import io.objectbox.query.QueryBuilder;
/**
* Created by lynn on 2018/2/10.
* @param <T> database entity
*
*/
public abstract class BaseBoxManager<T> {
protected Box<T> mBox;
Class<T> tClass;
public BaseBoxManager(Class<T> entityClazz){
this.tClass=entityClazz;
mBox= BoxConfig.getBoxStore().boxFor(tClass);
}
protected final void closeDatabase(){
mBox.closeThreadResources();
}
/**
* 插入一条记录
*
* @return The ID of the object within its box.
*/
public long insert(T entity) {
if (entity == null) return -1;
return mBox.put(entity);
}
/**
* 插入多条记录
*/
public void insert(List<T> entities) {
if (entities != null)
mBox.put(entities);
}
/**
* 删除所有数据
*/
public void deleteAll() {
mBox.removeAll();
}
/**
* 根据条件删除数据库中的数据
*/
public void delete(T object) {
mBox.remove(object);
}
/**
* 删除多条数据
*/
public void deleteList(List<T> objects) {
mBox.remove(objects);
}
/**
* 更新一条记录
*/
public long update(T object) {
return mBox.put(object);
}
/**
* 更新一条记录
*/
public void update(List<T> objects) {
mBox.put(objects);
}
/**
* @return Returns a builder to create queries for Object matching supplied criteria.
*/
public QueryBuilder<T> getQueryBuilder() {
return mBox.query();
}
/**
* 查询并返回所有对象的集合
*/
public List<T> queryAll() {
return getQueryBuilder().build().find();
}
/**
* 查询并返回 第一个对象
*/
public T QueryFirst() {
return getQueryBuilder().build().findFirst();
}
/**
* 获取对应的表名
*/
public abstract String getTableName();
}
采用glide获取网络图片
添加依赖
1
2
3//glide
implementation 'com.github.bumptech.glide:glide:4.6.1'
annotationProcessor 'com.github.bumptech.glide:compiler:4.6.1'只需添加一行就可以加载图片
1
2
3
4
5
6private void downloadImage(){
String imgUrl=mBookbean.getImages().getSmall();
if(!TextUtils.isEmpty(imgUrl)){
Glide.with(this).load(imgUrl).into(imgBook);//下载图片并显示到imageview上
}
}
timeline组件
时间线显示列表的组件,找到了一个GitHub上star比较多的组件。Timeline-View 上有详细介绍使用方法,只需要根据设计的样式稍作调整即可集成。
ButterKnife使用
使用butterknife可以减少繁琐的findviewbyid这样的代码,可直接通过注释来绑定组件。
添加依赖
1
2
3//butterknife
compile 'com.jakewharton:butterknife:8.8.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'注释组件
1
2
3
4@BindView(R.id.txt_book_name)
TextView txtBookName;
@BindView(R.id.txt_author)
TextView txtAuthor;绑定
1
ButterKnife.bind(BookDetailActivity.this);