本章内容:
1. 回顾SQLite相关操作
2. 高性能的ORM框架:GreenDao
3. 综合实例:搜索历史的实现
面试题:
简述SQLite数据库的操作。
如何将数据库文件和程序代码一起打包发布?
Assets和Raws有什么区别?
1.相同点:都不会被编译成二进制文件,保留原始的结构。
2.不同点:Raws里的文件会生成R资源id,Assets不行
Raws里不能创建其它文件夹,Assets可以
获得方法:
Raws:getResources().openRawResourc(id)
Assets:getAssets().open(File)
什么是ORM?
O:Object(对象:Java bean)
R:Relationship(关系:数据库的二维表)
M:Mapping(映射:关联)
ORM就是对象关系映射。
GreenDAO框架
GreenDAO框架就是一个ORM框架,是目前最快的ORM框架。
ORMLite、ActiveAndroid。。。
简单说:
GreenDAO能将数据库中的数据转化为Java对象。如下图:
GreenDAO框架的使用
https://github.com/greenrobot/greenDAO
GreenDAO的配置:
project的build.gradle:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.1.1'
}
}
module的build.gradle:
apply plugin: 'org.greenrobot.greendao'
dependencies {
compile 'org.greenrobot:greendao:3.1.1'
}
greendao{
daoPackage 'com.qianfeng.day3_greendao.db'
targetGenDir 'src/main/java'
}
使用GreenDAO:
1、创建Entity:
@Entity
public class User{
@Id(autoincrement = true)
private Long id;
private String username;
private String password;
}
2、Build —— Make Project
3、自动生成:DaoMaster、DaoSession、UserDao三个类
4、创建UserDao对象
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, "test.db");
SQLiteDatabase database = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(database);
UserDao dao = daoMaster.newSession().getUserDao();
5、调用UserDao的insert、update、query、delete方法
扩展:使用@ToMany实现表的关联
RXJava:
https://github.com/ReactiveX/RxJava
目前非常流行的事件驱动型框架,基于观察者模式,能够非常方便灵活地进行异步操作。
使用方法:
1、导入包,(x、y、z代表具体版本号)
compile 'io.reactivex:rxjava:x.y.z'
2、创建被观察者 Observable
3、创建观察者/订阅者 Subscriber
4、建立观察者和被观察者的关联
5、指定观察者和被观察者执行的线程
基本使用
//创建被观察者
Observable<String> observable = Observable.create(
new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
Log.i(TAG, "call: "+ Thread.currentThread().getName());
subscriber.onNext("Use Thread!!" );
}
});
//创建观察者
Subscriber<String> subscriber = new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.i(TAG, "onNext: " + s + "," + Thread.currentThread().getName());
}
};
//关联
observable.subscribe(subscriber);
线程切换
Observable.create(new Observable.OnSubscribe<String>() {
@Override
public void call(Subscriber<? super String> subscriber) {
Log.i(TAG, "call: "+Thread.currentThread().getName());
subscriber.onNext("Thread!");
}
})
//指定观察者执行的线程为UI线程,下面的类需要导入RxAndroid库
.observeOn(AndroidSchedulers.mainThread())
//指定被观察者执行的线程为新线程
.subscribeOn(Schedulers.newThread())
.subscribe(new Subscriber<String>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(String s) {
Log.i(TAG, "onNext: " + s +",run on:"+
Thread.currentThread().getName());
}
});
案例:加载网络图片
案例:RxJava与Retrofit结合
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'
compile 'io.reactivex:rxandroid:1.2.1'
compile 'io.reactivex:rxjava:1.2.1'
PullToRefresh
地址:https://github.com/chrisbanes/Android-PullToRefresh
使用步骤:
1、导入项目,new—import module— 导入library项目
2、引用项目,当前项目添加模块引用
3、使用PullToRefreshListView、PullToRefreshGridView等控件
常用方法:
//设置适配器
mListView.setAdapter(mAdapter);
//设置刷新模式,BOTH代表上拉和下拉
mListView.setMode(PullToRefreshBase.Mode.BOTH);
//设置刷新监听
mListView.setOnRefreshListener(
new PullToRefreshBase.OnRefreshListener2<ListView>() {
//上拉刷新
@Override
public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Refresh", Toast.LENGTH_SHORT).show();
mListView.onRefreshComplete();//停止刷新
}
},1000);
}
//下拉加载更多
@Override
public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Toast.makeText(MainActivity.this, "Load More", Toast.LENGTH_SHORT).show();
mListView.onRefreshComplete();
}
},1000);
}
});
//获得内部封装的ListView
ListView listView = mListView.getRefreshableView();
//添加头部视图
ImageView imageView = new ImageView(this);
imageView.setImageResource(R.mipmap.ic_launcher);
listView.addHeaderView(imageView);
高级应用:修改下拉刷新布局样式
1、自定义的刷新布局在LoadingLayout中。
2、在PullToRefreshBase中1108行对HeaderView和FooterView进行了初始化。
3、创建LoadingLayout的位置在PullToRefreshBase类的1325.
自定义步骤:
1、自定义loading_layout的布局资源.根据需求改变样式
2、loading布局资源在LoadingLayout中进行加载。对LoadingLayout类做修改。将不需要的控件删除以及其对于的方法。
3、自定义类,继承LoadingLayout,重写其中的方法。
4、getDefaultDrawableResId设置一个默认的图片
5、在构造器中对自定义的布局控件进行配置。
6、在根据需求,在下拉刷新,或者刷新中的回掉方法中,处理自己的业务逻辑。
7、在resetImpl方法中,对空间的属性进行重置。(重置的目的是为了下次,重新执行刷新动画)
8、在PullToRefreshBase类中的1327行,将自定义的LoadingLayout配置进去。
DrawerLayout
android自带的滑动抽屉视图
使用方法:
<DrawerLayout>
第一个子控件作为内容区
<Layout>
第二个子控件作为滑动抽屉
必须设置layout_gravity控制抽屉滑出方向
<View>
</DrawerLayout>
项目中可能用到的一些其它第三方框架:
图片轮播:
https://github.com/saiwu-bigkoo/Android-ConvenientBanner
缩放效果的侧滑菜单:
https://github.com/SpecialCyCi/AndroidResideMenu
ButterKnife依赖注入框架:
官网:https://github.com/JakeWharton/butterknife
如何在项目中使用ButterKnife
工程级别的gradle添加:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}}
模块级别的gradle添加:
apply plugin: 'android-apt'
android {
..}
dependencies {
compile 'com.jakewharton:butterknife:8.4.0'
apt 'com.jakewharton:butterknife-compiler:8.4.0'}
使用@BindView、@BindString、@OnClick注解
class ExampleActivity extends Activity {
@BindView(R.id.user) EditText username;
@BindView(R.id.pass) EditText password;
@BindString(R.string.login_error) String loginErrorMessage;
@OnClick(R.id.submit) void submit() {
// TODO call server...
}
@Override public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.simple_activity);
ButterKnife.bind(this);
// TODO Use fields...
}
}
使用ButterKnife完成主页框架。
面试题:用过哪些开源框架,是否研究过它们的源码?
自定义ButterKnife:使用注解+反射
OkHttp网络请求框架:
参考文档API、官网。
OkHttp是一个类似HttpUrlConnection的网络请求工具类。其重点在于优化网络请求方式。
OkHttp的强大体现在以下2个方面:
1. 更快:网络请求速度更快,支持HTTP/2技术,提升网络请求速度。当在HTTP/2不可用的情况下,会采用连接池,减少请求延迟,从而提高请求速度
2. 更省:更省流量,通过GZIP对数据进行压缩并结合缓存机制,从而压缩下载数据的大小、并且在一定的时效内缓存请求的数据,减少短时间内多次请求的流量消耗
面试题:GET和POST的区别是什么?
常用的Http请求:Post和Get方式
Get:参数包括在URL地址中,不安全,长度有限制,适用于不涉及重要信息的查询类操作
Post:参数在后台提交,安全,长度没有限制,适用登录、支付等涉及重要信息的操作
导入库文件:compile 'com.squareup.okhttp3:okhttp:3.2.0’
用法:
OkHttpClient mClient = new OkHttpClient();
GET同步请求:
Request request = new Request.Builder()
.url(URL)
.get()
.build();
Response response = null;
try {
response = mClient.newCall(request).execute();
String s = response.body().string();
return s;
} catch (IOException e) {
e.printStackTrace();
}
GET异步请求:
Post请求:
面试题:如何完成一个文件的下载?
文件下载:
Retrofit网络请求框架:
在OkHttp框架的基础上进行了再次封装,功能强大,使用简单。
特点:可以灵活添加各种格式转换库,进行数据解析更加方便
添加库:
compile 'com.squareup.retrofit2:retrofit:2.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'
compile 'com.squareup.retrofit2:converter-scalars:2.1.0’
用法:
定义数据访问接口
public interface HttpService {
@GET("/web/MyServlet")
Call<String> getName(@Query("name")String name);
@POST("/web/MyServlet")
Call<String> postName(@Query("name")String name);
}
通过Retrofit创建数据访问接口的实现对象
public class HttpUtils {
private static final String URL = "http://192.168.0.103:8080";
private static HttpService sHttpService = null;
public static HttpService getHttpService(){
if(sHttpService == null){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(URL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
sHttpService = retrofit.create(HttpService.class);
}
return sHttpService;
}
}
通过数据访问接口进行网络操作(和OkHttp相同)
HttpUtils.getHttpService().getName("chenheng")
.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
String body = response.body();
Log.i(TAG, "onResponse: "+body);
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
CardView 用法
CardView: cardElevation, cardMaxElevation, cardCornerRadius
RecyclerView的用法
LayoutManager, Adapter, Adapter.ViewHolder
RecyclerView与ListView比较
setOnItemClickListener
ViewHolder, Adapter
扩展部分:UltimateRecycerView
SwipeRefreshLayout
配置
事件回调
与RecyclerView的配合
极光推送的使用方法
1.登录极光推送官网:https://www.jpush.cn/
2.注册用户并登录
3.创建自己的应用,获得密钥和AppKey
4.下载Android客户端SDK,并集成到Android应用中
把libs考到项目中,添加jar包
模块gradle的android中添加:
sourceSets {
main {
jniLibs.srcDir("libs");
}
}
复制res目录覆盖程序res
修改Manifest文件
编码:
在Application类中,初始化极光推送
//初始化极光推送
JPushInterface.init(this);
//开启调试模式,发布时设置为false
JPushInterface.setDebugMode(true);
扩展:服务器端JPush的集成
JPushClient jpushClient = new JPushClient( "8b8747d3a8c95d36a301c4f0", "f545b6965ef2742ab358ecda");
PushPayload payload =PushPayload.newBuilder() .
setPlatform(Platform.android()) .
setAudience(Audience.all()) .
setNotification(Notification.android( text, "message", null)) .
build();
PushResult result = jpushClient.sendPush(payload);
第三方分享ShareSDK
集成各种社交平台
http://www.mob.com
ShareSDK AppKey:16c4a4897926c
包名:com.xray.daydaybasketball
微信AppId:wxb1c1405c2fe73430
密钥:6d7d78dd0a9af154b23a13d8c4e0e491
ZXing:Google官方提供的二维码解析包
https://github.com/zxing/zxing
导入ZXing包
生成二维码
使用MultiFormatWriter
BitMatrix encode(String, BarcodeFormat,int,int,Map)
需要将BitMatrix转为Bitmap
BitMatrix — int[] — Bitmap
解析二维码
使用MultiFormatReader
decode(BinaryBitmap,Map)
需要将Bitmap转为BinaryBitmap
Bitmap —— int[] —— RGBLuminanceSource
—— HybridBinarizer —— BinaryBitmap
二维码扫描
实现拍照功能需要手机摄像头支持,Camera类用于控制手机摄像头。
Camera类的主要方法:
1. 打开摄像头,并返回Camera对象
1. Camera.open()
2. 设置摄像头的参数
1. setParameters(Parameters)
3. 设置预览的显示 ,需要借助于SurfaceView
1. setPreviewDisplay(SurfaceHolder)
4. 开始预览
1. startPreview()
5. 停止预览
1. stopPreview()
6. 自动对焦
1. autoFocus(AutoFocusCallBack)
7. 拍照
1. takePicture(ShutterCallBack,PictureCallBack,PictureCallBack)
需要添加的权限:CAMERA
实现牌照的步骤:
1,初始化SurfaceView,使用SurfaceHolder添加Callback回调
2,在surfaceCreate方法中:打开摄像头,设置参数,设置预览界面,开始预览
3,点击牌照按钮:调用摄像头拍照方法,处理图片
4,在surfaceDestroy方法中:停止预览,释放摄像头