https://admin@localhost:8443/r/liuyuan.gitGIT工具使用
1、服务器搭建(截图见PPT)
2、客户端安装及使用
3、常见操作
4、注意事项:
a)链接的处理https://admin@localhost:8443/r/takeout.git
1、admin@删除
2、localhost换成ip地址
b)由于服务器存在安全证书
客户端如果想要链接上必须对此问题进行处理,即不做安全校验
Cmd中输入命令:git config --global --bool --add http.sslVerify false
c)工程提交时需要设置忽略文档信息(原则:在本地能够生产的文件都不需要提交)
d)代码更新时需要先从服务器获取最新的更新,然后拉取代码。
e)
MVC转换到MVP
MVC模式
M:model
V:view
C:controller
在Android中默认按MVC的方式构建项目,V—layout,C—Activity。
登陆案例代码分析。
MVP模式
M:model
V:view
P:presenter
我们这里把与业务有关的代码都放到了P中。
解耦和方式
1、利用配置文件,使用反射获取到需要加载的对象。
2、设计模式:单例、工厂、观察者……
Dagger2
Dagger2简介
1、什么是Dagger2?
Dagger是为Android和Java平台提供的在编译时进行依赖注入的框架。
编译时:编辑时生成代码(rebulid),我们完成所需对象的注入。(假设使用反射,应该是什么时候起作用?)。
2、为什么使用Dagger2?
Dagger2解决了基于反射带来的开发和性能上的问题。
3、做什么工作?
本项目中Dagger2主要用于做界面和业务之间的隔离。
使用手册
一、引入配置
1、添加dagger2的依赖
compile 'com.google.dagger:dagger:2.6'
2、编译时生成代码的插件配置(android-apt)
a)project的gradle中添加
buildscript {
dependencies {
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'
}
}
b)apt插件的使用
modle的gradle中添加
apply plugin: 'com.neenbedankt.android-apt'
c)关联Dagger2
dependencies {
apt 'com.google.dagger:dagger-compiler:2.6'
}
二、操作步骤(熟练掌握)、
三、深入解析(了解)
在操作中会使用到@Inject、@Module、@Provides、@Conponent注解,那么他们分别在完成什么工作?
MainActivityPresenter presenter=new MainActivityPresenter(this);
@Inject @Conponent @Module @Provides
MainActivity_MembersInjector
public voidinjectMembers(MainActivity instance) {
if(instance ==null) {
……}
instance.presenter=presenterProvider.get();
}
其实,Dagger2在使用这几个注解解决三个问题。
1.创建对象的代码放到那里去了?
2.创建好的对象给谁(指定接收者)?
3.如何将创建好的对象赋值给接收者?
l指定创建对象的类(组件)和方法
@Module:指定创建对象的类
@Provides:指定创建对象的方法
初始时:
publicclass MainActivityModule {
public String createString(){
return new String(“liutao”);
}
}
添加注解后:
@Moudle
publicclass MainActivityModule {
@Provides
public String createString(){
return new String(“liutao”);
}
}
l指定接收者
创建好的对象需要赋值给指定的目标,我们需要通过@Inject注解告知Dagger2容器,把已经创建好的对象赋值给谁。
public class MainActivity…..{
@Inject
String target;
}
l将接收者和创建好的对象联系在一起
通过@Component来指定工作由哪个接口完成,通过这个接口我们可以看到组件和接收者。
ButterKnife工具使用
配置依赖:compile 'com.jakewharton:butterknife:5.1.1'
安装插件:在plugins中搜索butterknife,安装Android ButterKnife Zelezny
控件初始化操作:
Retorfit
一、Retorfit简介
Retorfit是一个功能强大的联网工具。可以看成是OKHttp+数据解析(json、xml等)的组合。
说明文档:http://square.github.io/retrofit/
GitHub:https://github.com/square/retrofit
二、使用手册
1.引入配置
l添加Retrofit依赖:
compile'com.squareup.retrofit2:retrofit:2.1.0'
l使用Gson进行数据解析
compile'com.google.code.gson:gson:2.2.4'
l将Retorfit与Gson关联
compile'com.squareup.retrofit2:converter-gson:2.1.0'
2.使用步骤
1)创建Retorfit.Builder对象,通过Builder指定基本配置信息。
Retrofit.Builder builder = new Retrofit.Builder();
builder.baseUrl("http://localhost:8080/");
builder.addConverterFactory(GsonConverterFactory.create());
2)通过Builder构建Retorfit对象
Retrofitretrofit= builder.build();
3)配置链接和参数
public interface ResponseInfoAPI {
@GET("TakeoutService/login")
Call login(@Query("username") String username,@Query("password") String password);
}
注:ResponseInfo是服务器回复数据封装成的对象。
测试链接http://localhost:8080/TakeoutService/login?username="liutao"&password="bj"
4)完整链接组合
ResponseInfoAPI api = retrofit.create(ResponseInfoAPI.class);
5)执行联网操作
Call call =api.login(“itliutao”,”bj”);
call.enqueue(new Callback() {
@Override
public void onResponse(Response response, Retrofit retrofit) {
//结果处理
}
@Override
public void onFailure(Throwable throwable) {
//异常处理
}
});
请求方法:@GET / @POST
URL处理:测试链接http://localhost:8080/TakeoutService/login?username="liutao"&password="bj"
替换原则:
1、@Path -替换参数
@GET("/group/{id}/users")
public Call> groupList(@Path("id") int groupId);
2、@Query -添加查询参数
@GET("/group/{id}/users")
public Call> groupList(@Path("id") int groupId, @Query("sort") String sort);
3、@QueryMap -如果有多个查询参数,把它们放在Map中
@GET("/group/{id}/users")
public Call> groupList(@Path("id") int groupId, @QueryMap Map options);
Ormlite工具使用
配置
compile'com.j256.ormlite:ormlite-android:5.0'
使用
常用注解
@DatabaseTable(tableName = "t_user")
指定实体和表的一一对应关系
@DatabaseField()
指定属性与表中列的一一对应关系
常用配置说明:
主键:id = true
自增主键:generatedId = true
列名:columnName = "name"
是否为空:canBeNull =true
外键:foreign =true
示例:
@DatabaseTable(tableName ="t_address")
public classAddressBean {
@DatabaseField(id =true)
private int_id;
@DatabaseField(canBeNull =false)
privateStringgoodsAddress;
@DatabaseField(canBeNull =false)
privateStringvillage;
@DatabaseField(canBeNull =false,foreign =true,columnName ="user_id",foreignColumnName ="_id")
privateUserBeanuser;
}
@DatabaseTable(tableName ="t_user")
public classUserBean {
@DatabaseField(id =true)
private int_id;
@ForeignCollectionField(eager =true)
privateForeignCollectionaddressList;
}
DBHelper管理
与原声的DBHelper相同,主要负责数据库的创建和表的维护。需要继承OrmLiteSqliteOpenHelper类。
使用工具:TableUtils完成表的相关操作,如创建、清空、删除
项目整合
包结构划分。项目比较复杂时,大家开始动手完成代码前必须要想清除,代码是放在哪里的。
业务层联网操作
依据接口文档中给出的服务器回复信息,设置Retorfit。由于服务器回复的是Json文件,并且服务器地址一般情况下不会变动,所以Retorfit的创建可以在业务层基类中完成
newRetrofit.Builder().
baseUrl(Constant.HOME).
addConverterFactory(GsonConverterFactory.create()).
build();
从接口文档中我们知道,回复的数据格式是统一的,我们仅仅封装一个对象就可以满足访问网络的需求
与之对应的API接口设置一个就能满足需求。
不同的模块在处理时只需要增加对应的方法即可,方法返回的类型是相同的。所以我们自需要创建ResponseInfoAPI的实现类对象就能满足需求。
ResponseInfoAPI responseInfoAPI =retrofit.create(ResponseInfoAPI.class);
可以集成到业务的基类中。
联网回复结果处理
当获取到服务器返回数据后会出发设置好的Callback,两个方法如下:
public voidonResponse(Call call, Response response)
public void onFailure(Call call, Throwable t)
我们需要对回复的结果做进一步处理,首先必须要判断code值,如果为0表示当前请求操作服务器处理成功,返回用户想要数据,如果不为0表示服务器处理该请求出现问题,比如:用户名或密码输入错误。这个信息我们需要统一展示给用户。所以我们需要对两个方法进行统一处理。在onResponse中需要
ResponseInfo body = response.body();
if("0".equals(body.getCode())) {
// 服务器处理成功,可以解析data数据了parseDestInfo(body.getData());
}else{
String error=errorInfo.get(body.getCode());
onFailure(call,newRuntimeException(error));
}
如果出现服务器处理错误会出发onFailure方法,同时由于网络问题也会触发该方法,我们需要对出发来源进行区分,可以定义一个自己的异常,封装服务器返回错误提示信息,展示给用户,如果是网络问题则提示:请检查网络,或服务器忙等。代码如下(这里使用了RuntimeException)
public void onFailure(Call call, Throwable t) {
if(t instanceof RuntimeException){
showError(((RuntimeException)t).getMessage());
}
showError("服务器忙,请稍后重试……");
}
业务层数据库操作
数据库需要使用到DBHelper,所以我们在DBHelper类中实现了单例,这样就不用每次都创建了。
需要重点注意的问题,操作DBHelper时需要传递上下文,我们需要使用生命周期较长的Application作为参数,不能使用某个具体的Activity或Fragment对象。
公共布局处理
首先完成MainActivity,布局比较简单,我们经常实现,所以layout大家可以直接拷贝了。
问题是:很多项目中都会有这种需求,但Item的数量不等,我们不得不调整代码,有通用的实现方式吗?
注意我们Layou的底部导航部分内容。
这样进行布局的目的是我们刻意批量的处理各种事件。
比如:底部导航每个Item都有自己的点击事件,那么我们只需要获取到底部导航容器,对他的孩子(不包含孙子),循环一次就可以设置好点击事件。代码如下:
intchildCount =switcherContainer.getChildCount();
for(inti =0; i < childCount; i++) {
switcherContainer.getChildAt(i).setOnClickListener(switherOcl);
}
在某个孩子被点击后我们可以处理以下工作:
1、修改对应状态,达到切换图片背景和文字颜色的效果
2、切换Fragment,我们可以把用到Fragment按顺序添加到集合中,当点击某个按钮后,会获取到期再底部容器中的具体位置信息,位置从0开始,而Fragment集合也是从0开始基数,所以他们的位置是一一对应的。
这里边有一个让人非常恼火的问题,每个Item都有两张不同的图片,我们需要逐个完成选择器的编写,这里面给大家介绍一个插件,他可以帮助我们生产这部分代码,只要你每组图片的命名按照其规定要求就能够帮助我们生产选择器。
命名规则可以查询提供的官方文档。
操作截图:
Fragment切换
将每个底部容器Item对应的Fragment放到一个容器中,注意Fragment的添加顺序,需要与Item的顺序保持一致,然后我们就可以通过Item的index找到对应的Fragment进行切换了。