没有总结的知识就是empty
最近突然陷入了如何证明自己的能力困境。人家问的基本问题都不能很好的给出答案,弄得很低逼。自己接触android已经一年了,以前在学校又没有认真的跟着老师的步伐,放任自己的兴趣去研究,自己认为好的,自己骄傲的。久了才发现,其实这有点危险,最好导致自己和别人不一样,无法被别人正确理解自己。
我从那里学习
最基本的是:学校,网络,同学。但是我更加想说的是,自己如何通过一些资料,一些聊天来研究学习。那时候,我在深圳的短暂的日子了,我就发现了,他们开发方式很完备,甚至给我一种流水线的循序。再那里,我获得最有意义的是:一份代码规范的PDF,同事间谈话中的环信。总之,代码规范,环信。
内容代码规范,给我的影响很深,甚至,我现在再xml命名中,依旧保存着:模块+类型+功能(login_btn_enter)的命名方式,这个方式不单是清晰,而且发挥了编辑器代码提示的筛选,通过login限制搜索范围,btn,确定类型,enter当然是功能了。
环信,这个是当时,公司的QQ群上有一个同事提出的,他说现在很火。所以我就加入了研究环信,我获得环信demo的代码,这个代码更是让我体会到项目的。一个优秀像样的项目的代码是这样部署的?包是这样分类的?资源是这样嵌套的?
apiDemo,这个真的是一个很好的基础知识,首先,自己的SDK的目录下就有了,里面有各种各样的View的使用,而且使用的专业,不偏不倚。
support4Demo,这个很apiDemo一样。
如何分包
一般有:
com.qianhua.bestonn(整体包名:com+公司名+项目名)
base(一些base模版)
view(自定义的View)
ui(Activity,Fragment)
util(工具)
net(网络)
BestonnApplication.class
Constant.class
最近再研究MVP后,我发现这个模式对于高效开发有帮助,所以变成了模块化的分包:
login(登录)
chat(聊天)
……
因为mvp对于包下的class有一个公认的命名(如):
LoginActivity.class
LoginInteractor.class
LoginPresenter.class
LoginPresenterImpl.class
LoginView.class
BaseActivity的模版化意识
看别人的项目发现别人都有一个Base的意识,之后让自己的Activity来继承。后来,别人道出,这个一个模版化设计模式。模版方法模式:
定义一个操作中的骨架,而将一些步骤延迟到子类中。模版方法使得子类可用不改变一个算法的结构即可重新定义改方法的某些特定步骤。一般是一个抽象类。(固定算法骨架)
BaseActivity可以方便大家,统一一个结构,方便阅读。下面是我的对Volley的一个Base封装。出入以下考虑:
1)APP的网络可以独立一个类来处理,因为很多时候,网络获取到的数据要解析才能使用;
2)网络请求有两个必要的结果:失败,成功
3)输入请求标头等;
4)volley自己的使用是使用接口来处理的,格式化代码的时候好难看
package com.qianhua.bestonn3.net.base;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.HttpHeaderParser;
import com.android.volley.toolbox.StringRequest;
import com.qianhua.bestonn3.BestonnApplication;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Created by owant on 2015/10/14.
* 网络请求
*/
public abstract class VolleyRequest {
private Context mContext;
private String mUrl;
private int mRequestCode;
private Map<String, String> params;
private Map<String, String> header;
private StringRequest request;
private Object tag;
private Handler mHandler = null;
private Bundle mBundle = null;
public void initialize(Context mContext, String url, int request_method) {
this.mContext = mContext;
this.mUrl = url;
this.mRequestCode = request_method;
}
public void inputParams(Map<String, String> params) {
//测试的时候往往要打印一下输入参数的情况
Iterator<String> iterator = params.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next();
Log.i("input===>" + key, params.get(key));
}
this.params = params;
}
public void inputHeader(Map<String, String> headers) {
this.header = headers;
}
public void inputHandler(Handler mHandler) {
this.mHandler = mHandler;
}
public void setTag(Object tag) {
this.tag = tag;
}
public Handler getHandler() {
return mHandler;
}
public Context getContext() {
return this.mContext;
}
public void sendBunld(Bundle sendBundle) {
this.mBundle = sendBundle;
}
public Bundle getBundle() {
return this.mBundle;
}
/**
* 隐藏dialog
*
* @param dialog
*/
public void hideDialog(Dialog dialog) {
if (dialog == null) {
return;
}
if (dialog.isShowing()) {
dialog.dismiss();
}
}
/**
* 发送请求前,可以进行Dialog的显示处理等
*/
protected void onRepCommit() {
}
/**
* 返回请求成功响应
*
* @param response
*/
protected abstract void onNetResponse(String response);
/**
* 返回请求失败响应
*
* @param error
*/
protected abstract void onNetErrorResponse(VolleyError error);
/**
* 运行请求
*/
public void commit() {
onRepCommit();
request = new StringRequest(this.mRequestCode, this.mUrl,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
onNetResponse(response);
}
},
new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
onNetErrorResponse(error);
}
}) {
@Override
protected Map<String, String> getParams() throws AuthFailureError {
if (params != null) {
return params;
}
return super.getParams();
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
if (header != null) {
return header;
}
return super.getHeaders();
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
//解决中文乱码
String str = null;
try {
str = new String(response.data, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return Response.success(str, HttpHeaderParser.parseCacheHeaders(response));
}
};
//标识,用于撤销请求
if (tag != null) {
request.setTag(tag);
//防止重复请求
BestonnApplication.mQueue.cancelAll(tag);
}
BestonnApplication.mQueue.add(request);
}
}
View一个体验
对于视图,我们要考虑:空,非空。尽可能的提供这两种状态。我处理对于网络一般是:
<1>提供空和非空
<2>提供本地缓存的非空和空
这种做法,在很多app都有,而且我们的ListFragment都是提供了这些状态。进入:显示加载进度条,有数据显示数据,没有数据显示空状态代码如:
mListFragemnt.setListShown(boolean);
mListFragemnt.setEmptyText("没有数据");
其实listView也提供了setEmptyView(View);
在实现方面,用Fragment来实现最佳。直接将refreshView当成一个Fragment。
关于思考
有个一很悲哀的事情,搜索代替了思考,更有甚者,是见到别人做的东西就想到,这个模仿哪个什么的。其实这个就是他们自己的思考过程。
这种浅思考的解决方法无可厚非,但是,当你去真正创造的时候,才发现自己真的:什么都不会(除了搜索)。
一个相对正确的方法:
最后,总结这个是非常好的,文章总结,demo总结等