app开发总结 5 - android总结

一、概述

1.框架图:整体架构分为UI层、数据层,并结合MVC模式的使用
这里写图片描述

2.项目包结构:按模块进行划分
application:主要是自定义的Application
config:一些配置文件,如url、常量…
exception:自定义的异常
util:一些工具类
core:应用的核心部分,包含了各个跟业务相关的模块
这里写图片描述

3.core说明:作为应用的核心,包含了所有与业务相关的模块,主要有
activity、fragment:代表控制器,处理逻辑、事件交互、并作为 View、Model之间的桥梁
model:数据实体,分为resp、resq
view:视图,主要是自定义的视图,大部分都放到res/layout下
adapter:适配器
datalayer:数据层,又分为接口层、本地数据层
其它诸如receiver、service、provider等… 都应单独放在模块文件夹下
这里写图片描述

gradle依赖添加:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile files('libs/gson-2.3.1.jar')
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.facebook.fresco:fresco:0.10.0'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'de.greenrobot:greendao:2.1.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.android.support:support-v4:23.4.0'
}

二、UI层设计

BaseActivity、BaseFragment的封装:

public abstract class BaseActivity extends FragmentActivity implements View.OnClickListener{

    public String TAG = null;
    protected Context context;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //将当前activity压入栈顶
        ActivityStackManager.getInstance().pushActivity(this);

        //无标题栏
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

        context = this;
        TAG = getClass().getSimpleName();
    }

    /**
     * 初始化变量
     * 对于一个activity,通常会在onCreate中执行三个操作,分别是初始化成员变量,初始化视图,加载数据
     * 因此在基类定义好模板,由具体子类实现
     */
    protected void initVariable(){

    }


    /**
     * 初始化视图
     */
    protected void initViews(){

    }

    /**
     * 加载数据
     */
    protected void loadData(){

    }


    /**
     * 返回按键处理处理
     * @param keyCode
     * @param event
     * @return
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {

        if(keyCode == KeyEvent.KEYCODE_BACK){
            back();
            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

    /**
     * 返回键处理,默认是移除当前界面
     */
    protected void back(){
        ActivityStackManager.getInstance().popActivity();
    }

    @Override
    public void onClick(View v) {

    }

    /**
     * 显示输入键盘
     */
    public void displaySoftKeyboard() {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager != null) {
            View localView = getCurrentFocus();
            if (localView != null && localView.getWindowToken() != null) {
                inputMethodManager.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
            }
        }
    }

    /**
     * 关闭输入键盘
     */
    public void hideSoftKeyboard() {
        InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
        if (inputMethodManager != null) {
            View localView = getCurrentFocus();
            if (localView != null && localView.getWindowToken() != null) {
                IBinder windowToken = localView.getWindowToken();
                inputMethodManager.hideSoftInputFromWindow(windowToken, 0);
            }
        }
    }


public abstract class BaseFragment extends Fragment{

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    /**
     * 初始化变量
     * 通常会在fragment的onCreate中执行三个操作,分别是初始化成员变量,初始化视图,加载数据
     * 因此在基类定义好模板,由具体子类实现
     */
    protected void initVariable(){

    }


    /**
     * 初始化视图
     */
    protected void initViews(){

    }

    /**
     * 加载数据
     */
    protected void loadData(){

    }

}

三、Http工具设计

自定义OkHttp的回调:

/**
 * User: zjt
 * DateTime: 16/5/23 07:12
 *
 * 默认情况下okhttp的回调是在子线程,无法实现更新UI
 * 解决方案:重写onResponse()、onFailure()方法,并通过Handler转发到主线程即可
 *
 */
public abstract class OkHttpCallback implements okhttp3.Callback{

    /**
     * 主线程的Handler,全局
     * 只有UI线程默认Loop.prepare()、Loop.loop()过,如果在子线程中创建则需要手动处理
     */
    private static Handler mainHanlder =  new Handler(Looper.getMainLooper());

    @Override
    public void onResponse(Call call, final Response response) throws IOException {

        final String jsonStr = response.body().string();        //读取响应数据

        mainHanlder.post(new Runnable() {
            @Override
            public void run() {
                onResponse(jsonStr);      //读取完后通过handler转发到UI线程
            }
        });

    }

    @Override
    public void onFailure(Call call, final IOException e) {

        mainHanlder.post(new Runnable() {

            @Override
            public void run() {

                String errorMsg = "";
                if(e instanceof NotNetworkException){
                    errorMsg = "请检查您的网络!";
                }
                else if(e instanceof SocketTimeoutException){
                    errorMsg = "请求超时,请重试!";
                }
                else if(e instanceof ConnectException){
                    errorMsg = "无法连接到服务器,请稍后再试!";
                }
                else{
                    errorMsg = "未知错误!";
                }

                onFailure(e,errorMsg);               //通过handler转发到UI线程
            }

        });

    }

    /**
     * 请求成功 - UI线程回调
     * @param jsonStr
     */
    public abstract void onResponse(String jsonStr);

    /**
     * 请求失败 - UI线程回调
     * @param e
     */
    public abstract void onFailure(IOException e,String errorMsg);


}

OKHttpUtil:

/**
 * User: zjt
 * DateTime: 16/5/20 15:36
 *
 * http工具类
 */
public class OkHttpUtil {

    public static OkHttpClient okHttpClient;           //作为单例,只创建一次
    static {
        okHttpClient = new OkHttpClient();
    }

    /**
     * get异步请求,参数拼接到url后
     * @param url 请求路径
     * @param callback 回调
     */
    public static void doGet(String url, OkHttpCallback callback){

        if(isNetworkConnected(CustomApplication.getAppContext())){

            //1,封装请求Request
            Request request = new Request.Builder().url(url).build();

            //2,发送http请求并获取响应结果
            okHttpClient.newCall(request).enqueue(callback);

        }
        else{
            callback.onFailure(new NotNetworkException(),"请检查您的网络!");
        }

    }

    /**
     * post异步请求(将请求参数以json格式提交)
     * @param url 请求路径
     * @param params 参数,可为object、map
     * @param callback 回调
     */
    public static void doPostWithJson(String url,Object params,OkHttpCallback callback){

        Log.i("OkHttpUtil", "doPostWithJson: " + isNetworkConnected(CustomApplication.getAppContext()));

        if(isNetworkConnected(CustomApplication.getAppContext())){

            //1,设置content-type, post请求体
            MediaType mimeType = MediaType.parse("application/json; charset=utf-8");
            RequestBody body = RequestBody.create(mimeType, JsonUtil.parseToJsonStr(params));
            Request request = new Request.Builder().url(url).post(body).build();

            //2,发送http post请求
            okHttpClient.newCall(request).enqueue(callback);

        }
        else{
            callback.onFailure(new NotNetworkException(),"请检查您的网络!");
        }

    }

    /**
     * POST请求(key、value作为表单提交)
     */
    public void doPostWithForm(String url, Map<String,String> params, OkHttpCallback callback) throws IOException {

        if(isNetworkConnected(CustomApplication.getAppContext())){

            //封装请求参数
            FormBody.Builder formBuilder = new FormBody.Builder();
            for(Map.Entry<String,String> entry : params.entrySet()){
                formBuilder.add(entry.getKey(),entry.getValue());
            }
            RequestBody formBody = formBuilder.build();

            Request request = new Request.Builder().url(url).post(formBody).build();

            //发送http post请求
            okHttpClient.newCall(request).enqueue(callback);

        }
        else{
            callback.onFailure(new NotNetworkException(),"请检查您的网络!");
        }

    }

    /**
     * 是否有网络连接
     */
    public static boolean isNetworkConnected(Context context) {
        ConnectivityManager manager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo info = manager.getActiveNetworkInfo();
        return info != null && info.isAvailable();
    }

模拟接口调用:

    /**
     * 登录操作
     */
    private void login(){

        String phone = editUserName.getText().toString();
        String pwd = editPwd.getText().toString();

        loadingView.show();
        userApiManager.loginForPassword(phone, pwd, new OkHttpCallback() {

            @Override
            public void onResponse(String jsonStr) {
                loadingView.close();
                PromptUtil.toast(context,"登录成功!");
                startActivity(new Intent(context, IndexActivity.class));
            }

            @Override
            public void onFailure(IOException e, String errorMsg) {
                loadingView.close();
                PromptUtil.toast(context,errorMsg);

                loadingErrorView.show(errorMsg);
            }

        });

    }

三、Http统一错误处理

在onFailure中进行处理,并转发到UI线程,传入异常类型、以及描述

 @Override
    public void onFailure(Call call, final IOException e) {

        mainHanlder.post(new Runnable() {

            @Override
            public void run() {

                String errorMsg = "";
                if(e instanceof NotNetworkException){
                    errorMsg = "请检查您的网络!";
                }
                else if(e instanceof SocketTimeoutException){
                    errorMsg = "请求超时,请重试!";
                }
                else if(e instanceof ConnectException){
                    errorMsg = "无法连接到服务器,请稍后再试!";
                }
                else{
                    errorMsg = "未知错误!";
                }

                onFailure(e,errorMsg);               //通过handler转发到UI线程
            }

        });

四、自定义加载动画

/**
 * User: zjt
 * DateTime: 16/7/10 15:03
 *
 * 加载视图(仿美团)
 */
public class LoadingView extends RelativeLayout{

    private ImageView ivLoading;            //用于播放gif加载动画
    private TextView tvLoadingText;         //显示加载文字

    public LoadingView(Context context) {
        super(context);
        initView(context);
    }

    public LoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    /*
     * 初始化视图
     */
    private void initView(Context context){
        View.inflate(context,R.layout.loading_view,this);           //加载视图,并挂载到当前节点下

        ivLoading = (ImageView) findViewById(R.id.iv_loading);
        tvLoadingText = (TextView) findViewById(R.id.tv_loading_text);

    }

    /*
     * 显示加载视图
     */
    public void show(){
        setVisibility(View.VISIBLE);

        //开启加载动画
        AnimationDrawable drawables = (AnimationDrawable) ivLoading.getDrawable();
        if (!drawables.isRunning()) {
            drawables.start();
        }

    }

    /*
     * 关闭加载视图
     */
    public void close(){
        setVisibility(View.GONE);

        //关闭加载动画
        AnimationDrawable drawables = (AnimationDrawable) ivLoading.getDrawable();
        if (drawables.isRunning()) {
            drawables.stop();
        }

    }

}

显示错误信息的视图:

/**
 * User: zjt
 * DateTime: 16/7/10 15:40
 *
 * 调用http请求中,加载出错的提示
 */
public class LoadingErrorView extends RelativeLayout {

    private TextView tvErrorText;           //错误信息提示
    public Button btnReload;               //重新加载按钮

    public LoadingErrorView(Context context) {
        super(context);
        initView(context);
    }

    public LoadingErrorView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }

    /*
     * 初始化视图
     */
    private void initView(Context context){
        View.inflate(context, R.layout.loading_error_view,this);
        tvErrorText = (TextView) findViewById(R.id.tv_error_text);
        btnReload = (Button) findViewById(R.id.btn_reload);
    }


    /*
     * 显示加载视图
     */
    public void show(String errorMsg){
        setVisibility(View.VISIBLE);
        tvErrorText.setText(errorMsg);
    }

    /*
     * 关闭加载视图
     */
    public void close(){
        setVisibility(View.GONE);
    }



加载框的配置:
这里写图片描述
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值