文章目录
本周知识清单
- git学习与实践
- Android代码规范
- 网络请求框架使用小结
1. git学习与实践
1.1 git简介
git是一个分布式版本控制系统,用于代码管理,是多人合作代码合并解决冲突的一个利器
1.2 git安装
直接到官方网站上下载安装即可
1.3 git的基本使用功能
这部分先抛去远程仓库,先讲一下本地仓库的使用。步骤如下:
-
创建版本库
首先创建一个空的文件夹,然后初始化版本库
mkdir MyDemo
cd MyDemo
git init
- 编写自己的代码/文件等
- 把文件提交到仓库中
这里的意思就是,虽然在文件夹中是存在了你编写后的文件/代码,但你建立的仓库还没有加进来这些内容,所以要执行提交命令
git add readme.txt
git commit -m “写了一个readme文件”
或者
git add .
git commit -m “提交所有的代码/文件”
执行完这些命令后,后面应该会出现 一些文件被修改的情况
1.4 git当前状态查询
git status
该命令会提示有没有已修改/添加的文件等待被add/commit
git diff
该命令提示有哪些代码/文件与上一个版本有什么不同
1.5 git版本控制
git log
git log --pretty-oneline //去除其他无用消息,只显示id和注释
使用上面的命令查看之前的版本
git reset --hard HEAD^
回退到上一个版本
git reflog
查看所以版本记录,包括最新版本被回退的信息
找到,之前的新版本ID
git reset --hard ID
返回到新版本
1.6 添加远程仓库
注册一个git代码管理网站,常用的有github,码云,coding等
ssh-keygen -t rsa -C "youremail@example.com"
首先使用命令生成密钥,将密钥添加到选择的网站上,密钥一般存储在C:\Users\用户名称.ssh
如:github
建立和你本地项目同名的仓库
复制github仓库地址
git remote add origin https://github.com/xxx/MyDemo.git
建立连接
git push -u origin master
把本地仓库内容推送到远程仓库上,第一次推送需要加**-u**
1.7 分支管理
-
master主分支
一般由develop功能集成后合并
-
hotfix维护分支
直接从master分支fork出来的分支,用于bug修复,修复完成后应该马上合并回master分支和develop分支,master分支用新版本号,打上tag
-
develop发展分支
主要开发分支,新功能的分支由它扩展
-
feature功能分支
每个新功能位于自己的一个分支,使用decelop分支作为父分支,新功能完成后,合并回develop
-
预发布测试分支
develop功能集成后,由develop分支fork一个release发布分支,release分支主要用于bug修复,文档生成和其他面向发布的任务,测试完毕后合并到master分支,并分配一个版本号打上Tag
1.7.1 创建分支
创建dev分支,并切换到dev分支
git branch dev
git checkout dev
合并成一句话
git checkout -b dev
查看所有分支
git branch
在dev分支上编写代码,
提交
git push origin [分支名称]
git checkout master
切换到master分支
把dev分支的结果合并到master分支上
git merge dev
合并完成后,删除dev分支
git branch -d dev
1.7.2 解决冲突
在多人合作开发中,master不会只有你自己一个合并更新的,当另一个人更新了master,你再合并的分支的话就会产生冲突
- 如在本地仓库中master和自己的分支产生冲突
Auto-merging readme.txt
CONFLICT (add/add): Merge conflict in readme.txt
Automatic merge failed; fix conflicts and then commit the result.
git会把所有修改过的内容都整合在一起,这里需要自己手动修改
上传、提交、删除
git add .
git commit -m “整合”
git push origin master
git branch -d [分支名字]
- 远程仓库和其他人更新同一个分支出现冲突时
git push origin master
error: failed to push some refs to ‘https://github.com/Dream97/GitDemo.git’
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push --help’ for details.
如上,当我想更新master分支时,发现远程的分支早就被别人修改过,抛出错误
我需要把远程的仓库pull下来
git pull
执行到这一步发现我的代码又被合并了,手动修改
git add .
git commit -m “整合”
git push origin master
有时候git pull会失败,是因为没有指定本地分支和远程分支的链接,需要配置远程库和本地的链接
git branch --set-upstream-to=origin/[名字] [名字]
git pull
1.8 标签
标签(tag)用于标识版本的的一个快照,指向某个commit的指针,创建和删除标签都是瞬间完成的
git checkout master //切换到要打标签的分支
git tag v1.0 //打新标签
git tag //查看所有标签
也可以把标签打到历史提交的commit上
git log --pretty=oneline --abbrev-commit //查找历史提交
git tag v0.9 [历史commit id]
git tag
查看标签信息
git show v0.9
指定标签信息
git tag -a v0.9 -m “debug version”
推送标签
git push origin v0.9
git push origin --tags //推送全部尚未推送到远程的本地标签
删除本地标签
git tag -d v0.9
删除远程标签
git tag -d v0.9
git push origin :refs/tags/v0.9
2.Android代码规范
公司给的代码规范本来就有一份文档,但是文档还是有点长的,所以这里就摘取点比较重要的来记录一下
2.1 排版
- 缩进风格,缩进空格4个
- 长表达式/语句/参数多行书写,操作符放在新行之首
- 对齐使用空格键
- 操作符的前后间隔
a) ,逗号;分号后面加空格
b) = >= 等比较操作符前后加空格
c) .前后不加空格
d) {}代码块与前面的括号要用空格隔开
2.2 注释规范
1.文件注释:文件头部,包名之前
2.类和接口注释:package关键字之后,class或者interface之前
3.类和接口的注释内容:
/**
* <一句话描述>
* <功能详细简述>
* @author [作者]
* @version [版本号, YYYY-MM-DD]
* @see [相关类/方法]
* @since [产品/模块版本]
* @deprecated [已废弃说明]
*/
4.方法的注释内容
推荐使用@exception标注Runtime异常,@throws标注非Runtime异常
/**
* <一句话功能简述>
* <功能详细描述>
* @param [参数1] [参数1说明]
* @param [参数2] [参数2说明]
* @return [返回类型说明]
* @exception/throws [违例类型] [违例说明]
* @see [类、类#方法、类#成员]
* @deprecated
*/
5.在程序块结束行右方加注释标记,表明程序块的结束
if (...) {
}//end of if (...) 指明是哪条if语句结束
while (...) {
}//end of while(...)指明哪条if语句结束
2.3 命名规范
1.包名:小写
com.公司名.产品名.模块名称
com.公司名.部门名称.项目名称
2.类名:意义完整的英文描述,首字母大写
3.方法名:第一个字母小写
4.资源文件,id命名:全部小写,多个单子用下划线隔开
5.打包发布的安装包命名规则:“项目名-发布版本类型-版本名-编译日期”
a)dev:开发版,多数功能尚未完成
b)alpha:内测版,功能较不稳定
c)beta:册数版,功能较为稳定
d)release:发布版本
6.普通类的属性以一个小写"m"开头,其余大小写混合法,内部类的属性以"mm"开头
7.资源文件的命名:“btn_selector”,前缀使用:背景图片(bg)、图标图片(ic)
8.布局文件:"前缀_用途"如:activity_login.xml
9.View控件id:“tv_msg”,前缀如:TextView(tv)、EditText(et)、ProgressBar(pb)、LinearLayout(ll)、RelativeLayout(rl)、GridView(gv)等
2.3 JTEST规范
- 使用System.arraycopy(),不使用循环来复制数组
- finally 再异常处理时提供 finally块来执行任何清除操作。如果抛出一个异常,那么相匹配的catch子句就会执行,然后控制就会进入finally块(如果有的话)。finalize方法名。Java技术允许使用 finalize() 方法在垃圾收集器将对象从内存中清除出去之前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对这个对象调用的。它是在Object类中定义的, 因此所有的类都继承了它。子类覆盖finalize()方法以整理系统资源或者执行其他清理工作。
finalize() 方法是在垃圾收集器删除对象之前对这个对象调用的。 - 初始化时不要使用类的非静态属性。
说明:你用一个非静态属性去初始化一个变量,有可能非静态属性自己本身还没有初始化。 - 显式初始化所有的局部变量。
因为没有初始化的字段会是一个潜在的bug,如一个整数开始你不能确定什么值就初始化一个0给它 - 声明方法违例的时候不要使用 Exception ,应该使用它的子类。
Exeption报的异常没有它的子类具体。例如,DataFormatException,如果出异常就知道是数据格式异常。 IOException,就知道是IO操作的异常 - 使用StringBuffer的时候设置初始容量。在创建StringBuffer对象时java会默认分配一段空间给它,默认的空间可能过大,这样就浪费空间。在程序运行过程中可能默认的空间不够java又要重新创建一个StringBuffer这样浪费时间,
- 线程同步中,使用 notifyAll() 代替 notify()。
- 非同步方法中不能调用 wait() , notify() 方法。
- 使用wait(),notify()代替while(),sleep()。sleep()方法是使线程停止一段时间的方法。在sleep 时间间隔期满后,线程不一定立即恢复执行。这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非(a)“醒来”的线程具有更高的优先级(b)正在运行的线程因为其它原因而阻塞。wait()是线程交互时,如果线程对一个同步对象x发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。
- 实现 equals() 方法时,先用 getClass() 或者 instanceof 进行类型比较,通过后才能继续比较。首先两个对象先用getClass()获取它们所属的类,再用instanceof看这两个对象是不属于同一个类,如果不是,就不用equals()比较了。
- 不要使用 Date[] 而要使用 long[] 替代。基本类型数据运算效率更高
2.4 国际化
1.不要使用一个字符进行逻辑操作,使用Characater。如果代码要在一个国家环境中运行的话。我们可以使用字符比较方法,这些方法使用统一字符比较标准来定义字符的属性的。
public class CLOFixed {
public boolean isLetter (char ch) {
boolean _isLetter = Character.isLetter(ch);
return _isLetter;
}
}
2.不要进行字符串连接操作,使用MessageFormat 。
3.使用 StringTokenizer 代替 indexOf() 和 substring() 。
4.不要使用 Date.toString(),Time.toString()方法。'DateFormat’类提供了一个预定义的格式类型来指定本地的格式。
5.字符和字符串常量应该放在资源文件中。
6.不要使用数字的 toString() 方法。
7.不要使用 String 类的 compareTo(), equals() 方法。
建议不要使用’String.equals ()’方法,因为在统一字符比较标准中不一定按照相关的顺序来比较。 ‘Collator’提供的预定义整理规则来排序string,Collator类调用’getInstance ()’方法,一般来说,可以为默认的本地创建一个Collator。例如:Collator myCollator = Collator.getInstance (); 创建Collator的时候你也可以指定一个特殊的locale。 例如:Collator myFrenchCollator = Collator.getInstance (Locale.FRENCH); 然后就可以调用’Collator.compare ()’来执行一个本地的字符比较myCollator.compare (s1,s2);
3 网络请求框架使用小结
Android开发大多数的时候是使用HTTP来进行网络请求的。HTTP 请求一般采用原生的 HttpClient 和 HttpUrlConnection 的两种网络访问方式。可是在 Android 5.0 的时候 Google 就不推荐使用 HttpClient 了,到了 Android 6.0(api 23)SDK,不再提供 org.apache.http.*(只保留几个类)为了更方便快捷地使用HTTP请求,我们往往会自己封装网络请求类或者使用其他第三方网络请求框架。下面总结一下曾经用过的两个网络请求框架Volley 和 OkHttp
3.1Volley
2013年 Google I/O大会 适用于数据量不大但通信频繁的网络操作
1、下载Volley库放在libs目录,add到工程中,下载地址http://central.maven.org/maven2/com/mcxiaoke/volley/library/
2、基于请求队列,基于全局性/局部性
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
3、使用get方法请求百度
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
StringRequest mStringRequest = new StringRequest(Request.Method.GET,
"http://www.baidu.com",
new Response.Listener<String>() {
@Override
public void onResponse(String Response) {
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyErroe error){
}
}
});
//将请求添加到请求队列中
mQueue.add(mStringRequest);
4、使用JsonRequest转换成Java实体类
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
JsonObjectRequest mJsonObjectRequest = new JsonObjectRequest(
Request.Method.POST,
"http://...",
new Response.Listener<JsonObject>() {
@Override
public void onResponse(JsonObject response) {
MyBean myBean = new Gson().fromJson(response.toString(),MyBean.class);
...
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyErroe error){
}
});
mQueue.add(mJsonObjectRequest);
5、使用ImageLoader加载图片
ImageLoader的内部使用ImageRequest来实现,先显示默认图片,图片加载完成才会显示到ImageView
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
ImageLoader imageLoader = new ImageLoader(mQueue, mew BitmapCache());
ImageLoader.ImageListener listener = ImageLoader.getImageListener();
imageLoader.get("http://...",
listener);
6、使用NetWorkImageView加载图片
<com.android.volley.toolbox.NetworkImageView
android:id="@+id/nv_image"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_centerHorizontal="true">
</com.android.volley.toolbox.NetworkImageView>
代码中使用
RequestQueue mQueue = Volley.newRequestQueue(getApplicationContext());
ImageLoader imageLoader = new ImageLoader(mQueue,new BitmapCache());
nv_image.setDefaultImageResId(R.drawable.ic_default);
nv_image.setErrorImageResId(R.drawable.ic_error);
nv_iamge.setImageUrl("http...",imageLoader);
3.2 OkHttp
OkHttp出自Square公司,在目前开发中是一个使用频率非常高的一个网络请求框架。特别是在Square发布Retrofit后,基于OkHttp的Retrofit+RxJava基本上成为了Android主流框架。下面了解一下okHttp的基本使用
1、配置gradle
最新版本查看github地址
2、异步GET请求
Request.Builder requestBuilder = new Requet.Builder().url("http:...");
requestBuilder.method("GET", null);
Request request = requestBuilder.build();
OkHttpClient mOkHttpClient = new OkHttpClient();
Call mCall = mOkHttpClient.newCall(request);
mCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
String str = response.body().string();
}
});
onResponse的回调并非UI线程
3、异步POST请求
OkHttp3异步请求使用FormBody ,OkHttp2.x使用FormEncodingBuilder
RequestBody formBody = new FormBody.Builder()
.add("key","value")
.build();
Request request = new Requet.Builder()
.url("http:....")
.post(formBody)
.build();
OkHttpClient mOkHttpClient = new OkHttpClient();
Call mCall = mOkHttpClient.newCall(request);
mCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
String str = response.body().string();
}
});
4、文件和参数混合上传
OkHttpClient client = new OkHttpClient();
MultipartBody.Builder builder = new MultipartBody.Builder();
if (map!=null)
{
for (Map.Entry<String,String> entry:map.entrySet())
{
builder.addFormDataPart(entry.getKey(),entry.getValue()); //添加请求参数到请求体
}
}
File file = new File("文件路径");
if(file.exists()){
Log.d(TAG, "post3: 文件存在");
String TYPE = "application/octet-stream";
RequestBody fileBody = RequestBody.create(MediaType.parse(TYPE),file);
RequestBody requestBody = builder
.setType(MultipartBody.FORM)
.addFormDataPart("detail_image",file.getName(),fileBody)
.build();
Request request = new Request.Builder()
.url(address)
.post(requestBody)
.addHeader("Authorization","Bearer "+CommonVari.token)
.build();
}else {
Log.d(TAG, "post3: 文件不存在");
RequestBody requestBody = builder
.setType(MultipartBody.FORM)
.build();
Request request = new Request.Builder()
.url(address)
.post(requestBody)
.addHeader("Authorization","Bearer "+CommonVari.token)
.build();
}
client.newCall(request).enqueue(callback);
5、异步下载文件
Request request = new Requet.Builder()
.url("http:....")
.build();
OkHttpClient mOkHttpClient = new OkHttpClient();
Call mCall = mOkHttpClient.newCall(request);
mCall.enqueue(new Callback() {
@Override
public void onFailure(Call call, IOException e) {
}
@Override
public void onResponse(Call call, Response response) {
InputStream inputStream = response.body().byteStream();
FileOutputStream outputStream = response.body().byteStream();
String filePath = "";
try {
if (Environment.getExternalStorageState()
.equals(Environment.MEDIA_MOUNTED)) { //如果安装了SD卡
filePath = Environment.getExternalStorageDirectory().
getAbsolutePath();
} else { //没有安装SD卡
filePath = getFilesDir().getAbsolutePath();
}
File file = new File(filePath,"xxxx.txt");
if(null != file) {
outputStream = new FileOutputStream(file); //指定输出某文件
byte[] buffer = new byte[2048];
int len = 0;
while((len = inputStream.read(buffer)) != -1) {
FileOutputStream.write(buffer, 0, len);
}
}
outputStream.flush();
} catch(IOException e) {
}
}
});
6、设置超时时间和缓存
File sdcache = getExternalCacheDir();
int cacheSize = 10 * 1024 * 1024;
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.connectTimeout(15,TimeUnit.SECONDS)
.writeTimeout(20,TimeUnit.SECONDS)
.readTimeout(20,TimeUnit.SECONDS)
.cache(new Cache(sdcache.getAbsoluteFile(), cacheSize));
mOkHttpClient = builder.build();
参考资料
[2]Git教程(廖雪峰)