Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 完整Android項目搭建全過程

完整Android項目搭建全過程

編輯:關於Android編程

這篇博客也算是本人從事開發以來的一個總結,以前寫博客是為了裝逼,現在是為了成長,一個項目如果剛開始的框架沒有搭建好,接下來的維護工作將變得異常困難,我們公司的按項目就是因為一開始的框架沒有搭建好,只迭代了兩個版本便維護不下去了,只能是請高人重新設計的框架,一切重新來過。 不同類型的項目對框架的要求自然不同,但是有一點是相同的,那就是,首先對基礎語法進行封裝,相應工具類、方法樣式的封裝,前期的封裝可以避免後期項目無休止的重構代碼,也就不會出現因頻繁的改動需求導致代碼大量冗余。

廢話不多說,進入正題,要開始一個移動端項目搭建,一個最基本的前提條件就是要有完整的條理的產品需求,專業的產品原型圖,這一切都是產品經理來做的,如果你們公司沒有產品經理,那麼你也就只能自求多福了,當然你有一個天天把就跟淘寶一樣這句話掛在嘴邊的二逼產品經理,你也只能自求多福了。 對一個Android項目而言,前界面樣式的抽取,方法的封裝,工具類的導入,第三方sdk的繼承很重要

讓我們從BaseActivity和BaseFragment的封裝開始吧,為什麼要封裝BaseFragment和BaseActivity呢,我想你不會願意同樣的方法同樣的代碼照抄十遍吧,在BaseActivity和BaseFragment中我們可以定義一些接口或者抽象方法,以方便在其子類中執行

​代碼如下:

BaseActivity(abstract)這樣是為了一些抽象方法實現,而且不用再清單文件中注冊

import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import com.xxx.baseproject.MyApp;
import com.xxx.baseproject.R;
import com.xxxx.baseproject.util.NetUtils;
import com.xxx.baseproject.util.StatusBarCompat;

/**
 * Created by xuenan on 2016/5/23.
 */
public abstract class BaseActivity extends AppCompatActivity{

    //布局文件ID
    protected abstract int getContentViewId();
    //Activity基本樣式,功能

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //將ActionBar隱藏        
        /**
         *說到Actionbar,這是一個又丑又沒有用的東西,還得想方設法隱藏它
         *隱藏ActionBar的方法有好幾種,
         *一種是在Theme主題中設定Theme.AppCompat.Light.NoActionBar
         *或者在某個activity的主題中設定,這都是在清單文件中操作的
         *第二種就是在Activity調用setContentView()之前調用
         *requestWindowFeature(Window.FEATURE_NO_TITLE);
         *或者
         *requestWindowFeature(Window.FEATURE_NO_TITLE);
         *supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
         *這兩種方法的區別在於你的Activituy所繼承的是什麼Activity
         *像本文,繼承的是v7包中的AppCompatActivity,選用後者
         */
         //實現沉浸式狀態欄,後邊會說
        StatusBarCompat.compat(this);
        MyApp app = (MyApp) getApplication();
        //將每一個Activity都加入一個集合,用於程序退出
        app.addActivity(this);
        //用於網絡監測
        if(!NetUtils.isConnected(BaseActivity.this)){
            AlertDialog.Builder builder = new AlertDialog.Builder(BaseActivity.this);
            builder.setIcon(R.mipmap.ic_launcher);
            builder.setTitle("提示");
            builder.setMessage("當前沒有可用網絡,是否進入網絡設置界面");
            builder.setNegativeButton("確定", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                    NetUtils.openSetting(BaseActivity.this);
                }
            });
            builder.setPositiveButton("取消",null);
            builder.create().show();
        }
    }
}

BaseFragment(abstract)道理同上

import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by xuenan on 2016/5/23.
 * 一般情況下,為了向下兼容,我們采用v4包中的Fragment
 */
public abstract class BaseFragment extends Fragment{
    protected BaseActivity mActivity;
    //封裝抽象方法用於在fragment中初始化控件,增加代碼的條理性
    protected abstract void initView(View view, Bundle savedInstanceState);

    //獲取fragment布局文件ID
    protected abstract int getLayoutId();

    //獲取宿主Activity,不在使用getActivity()獲取Activity對象
    protected BaseActivity getHoldingActivity() {
        return mActivity;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        this.mActivity = (BaseActivity) activity;
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(getLayoutId(), container, false);
        initView(view, savedInstanceState);
        return view;
    }
}

對一個Android程序而言,有一個全局的Application(不要忘記在清單文件中注冊)是很重要的,主要用來初始化一些東西,比如地圖,推送,異常檢測,網絡請求。。。等等東西

import android.app.Activity;
import android.app.Application;

import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import com.xxx.baseproject.util.CrashHandler;
import com.xxx.baseproject.util.FunctionUtils;
import com.xxx.baseproject.util.LogUtils;

import java.util.ArrayList;
import java.util.List;


/**
 * Created by xuenan on 2015/12/31.
 */
public class MyApp extends Application{
    private static MyApp instance;
    /**
     * 01. 建立  請求隊列
     * 02. 將 請求隊列 加入到 AndroidMain.xml中
     * 03.
     */
    //本例使用Volley作為請求框架,它代表請求隊列
    private static RequestQueue queue;
    //存放Activity的List集合
    private List activityList = new ArrayList<>();
    //單例模式獲得Application對象
    public static MyApp getInstance() {
        return instance;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        instance=this;
        //異常處理類,實現了UncaughtExceptionHandler接口,
        //當程序發生異常時使程序優雅的退出
        CrashHandler crashHandler = CrashHandler.getInstance();
    //用單例模式或者Volley請求隊列
        queue= Volley.newRequestQueue(this.getApplicationContext());
        //對ImageLoader進行初始化
        FunctionUtils.setCustomImageLaoder(getApplicationContext());
    }
    //入口
    public static RequestQueue getQueue(){
        return queue;
    }
    /**
     * add the activity in to a list end
     * @param activity
     */
    public void addActivity(Activity activity) {
        try {
            if (activity != null && activityList != null) {
                int size = activityList.size();
                if (checkActivityIsVasivle(activity)) {
                    removeActivity(activity);
                    activityList.add(activityList.size(), activity);
                } else {
                    activityList.add(activity);
                }
                size = activityList.size();
                for (int i = 0; i < size; i++) {
                    LogUtils.i("addActivity ==[" + i + "]" + " " + activityList.get(i));
                }
            }
        } catch (Exception e) {
            LogUtils.e("addActivity" + e.getMessage());
        }

    }

    /**
     * remove the finished activity in the list.
     * @param activity
     * the activity is removed from activityList
     */
    public void removeActivity(Activity activity) {
        try {
            if (activityList != null) {
                activityList.remove(activity);
                LogUtils.i("removeActivity==" + " " + activity + "activityList.size===" + activityList.size());
            }
        } catch (Exception e) {
            LogUtils.e("removeActivity" + e.getMessage());
        }
    }
    /**
     * 判定某個Activity的狀態,
     * */
    public boolean checkActivityIsVasivle(Activity activity) {
        LogUtils.i(" " + activityList.contains(activity));
        return activityList.contains(activity);
    }

    /**
     * finish all the activity in the list.
     *干掉所有的Activity用於程序退出
     * the activity calling this method hold the context
     */
    public void finishAllActivity() {
        if (activityList != null) {
            int size = activityList.size();
            for (int i = size - 1; i >= 0; i--) {
                Activity activity = activityList.get(i);
                if (activity != null) {
                    activity.finish();
                }
                LogUtils.i("finishAllActivity ==[" + i + "]" + " " + activity);
                activityList.remove(activity);
            }
        }
    }
}

網絡請求框架的封裝,以Volley為例子
請求回調

import com.android.volley.Response;
import com.android.volley.VolleyError;


/**
 *  抽象出 成功的監聽和失敗的監聽
 *  用來回調信息
 * @author yuan
 *
 * @param 
 */

public abstract class VolleyHandler {


    public Response.Listener reqLis;
    public Response.ErrorListener reqErr;

    public VolleyHandler() {
        // 初始化 變量
        reqLis = new reqListener();
        reqErr = new reqErrorListener();
    }

    public abstract void reqSuccess(T response);

    public abstract void reqError(String error);

    /**
     * 成功後的監聽
     *
     * @author yuan
     *
     */
    public class reqListener implements Response.Listener {

        @Override
        public void onResponse(T response) {
            // 使用抽象函數 設置 回調函數 reqSuccess
            reqSuccess(response);
        }
    }

    /**
     * 失敗後的監聽
     *
     * @author yuan
     *
     */
    public class reqErrorListener implements Response.ErrorListener {

        @Override
        public void onErrorResponse(VolleyError error) {
            // 設置回調函數 使用 抽象方法 ReqError
            reqError(error.getMessage());
        }
    }
}

請求方法封裝

import android.app.Activity;
import android.graphics.Bitmap;
import com.android.volley.AuthFailureError;
import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request.Method;
import com.android.volley.RetryPolicy;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.xxx.baseproject.MyApp;
import org.json.JSONObject;
import java.util.Map;


/**
 * @author xuenan
 *請求超時設置三個參數的含義  等待時間  重復請求次數 下次請求等待時間
 */
public class VolleyHttpRequest{
    /** 1.
     * StringRequest GET方式 
     * @param url 地址
     * @param volleyRequest 回調函數
     */
    public static void String_request(String url,VolleyHandler volleyRequest){
        Volley_StringRequest(Method.GET, url,null, volleyRequest);
    }

    /** 1.
     * StringRequset POST方式
     * @param url 地址
     * @param map 參數
     * @param volleyRequest 回調函數
     */
    public static void String_request(String url,final Map map,VolleyHandler volleyRequest){
        Volley_StringRequest(Method.POST,url,map,volleyRequest);
    }
    /**1.
     * 封裝 StringRequest 數據請求
     * @param method 方式
     * @param url 地址
     * @param params 參數
     * @param volleyRequest 回調對象
     */
    private static void Volley_StringRequest(int method,String url,final Map params,VolleyHandler volleyRequest){
        StringRequest stringrequest=new StringRequest(method, url,volleyRequest.reqLis,volleyRequest.reqErr){
            //傳遞參數
            @Override
            protected Map getParams() throws AuthFailureError {
                return params;
            }
            //設置請求超時
            @Override
            public RetryPolicy getRetryPolicy() {
                RetryPolicy retryPolicy = new DefaultRetryPolicy(15000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                return retryPolicy;
            }
        };
        stringrequest.setTag("stringrequest");
        MyApp.getQueue().add(stringrequest);
    }

    /**2.
     * JsonObjectRequest GET 請求
     * @param url 請求地址
     * @param volleyRequest  回調函數對象
     */
    public static void JsonObject_Request(String url,VolleyHandler volleyRequest){
        Volley_JsonObjectRequest(Method.GET, url, null, volleyRequest);
    }

    /**2
     * JsonObjectRequest POST 請求
     * @param url 請求地址
     * @param jsonObject 請求參數
     * @param volleyRequest 回調函數對象
     */
    public static void JsonObject_Request(String url,JSONObject jsonObject,VolleyHandler volleyRequest){
        Volley_JsonObjectRequest(Method.POST,url,jsonObject,volleyRequest);
    }

    /**2.
     * 封裝 JsonObjectRequest 請求方法
     * @param method 方式
     * @param url 地址
     * @param jsonObject  參數
     * @param volleyRequest  回調函數對象
     */
    private static void Volley_JsonObjectRequest(int method,String url,JSONObject jsonObject,VolleyHandler volleyRequest){
        JsonObjectRequest jsonObjectRequest=new JsonObjectRequest(method,url,jsonObject,volleyRequest.reqLis,volleyRequest.reqErr){
            //設置請求超時
            @Override
            public RetryPolicy getRetryPolicy() {
                RetryPolicy retryPolicy = new DefaultRetryPolicy(15000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                return retryPolicy;
            }
        };
        jsonObjectRequest.setTag("jsonObjectRequest");
        MyApp.getQueue().add(jsonObjectRequest);
    }
    /**3.
     * ImageRequest 默認大小 原圖不變
     * @param url 地址
     * @param volleyRequest 回調函數
     */
    public static void Image_request(String url,VolleyHandler volleyRequest){
        Volley_ImageRequest(url, 0, 0, volleyRequest);
    }

    /**3.
     * ImageRequest 自定義的縮放
     * @param url 地址
     * @param maxWidth 最大寬度
     * @param maxHeight 最大高度
     * @param volleyRequest 回調函數
     */
    public static void Image_request(String url,int maxWidth,int maxHeight,VolleyHandler volleyRequest){
        Volley_ImageRequest(url, maxWidth, maxHeight, volleyRequest);
    }


    /**3.
     * 封裝 ImageRequest 請求方法
     * @param url 地址
     * @param maxWidth 最大寬度
     * @param maxHeight 最大高度
     * @param volleyRequest 回調函數對象
     */
    private static void Volley_ImageRequest(String url,int maxWidth,int maxHeight,VolleyHandler volleyRequest){
        ImageRequest imageRequest=new ImageRequest(url,volleyRequest.reqLis, maxWidth, maxHeight, Bitmap.Config.ARGB_8888,volleyRequest.reqErr){
            //設置請求超時
            @Override
            public RetryPolicy getRetryPolicy() {
                RetryPolicy retryPolicy = new DefaultRetryPolicy(15000,DefaultRetryPolicy.DEFAULT_MAX_RETRIES, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
                return retryPolicy;
            }
        };
        imageRequest.setTag("imageRequest");
        MyApp.getQueue().add(imageRequest);
    }


    /**
     * 4.
     * 自定義圖片的寬度值
     * @param url
     * @param imageListener
     * @param maxWidth
     * @param maxHidth
     */
    public static void Image_Loader(String url,ImageLoader.ImageListener imageListener,int maxWidth,int maxHidth){
        Volley_ImageLoader(url, imageListener, maxWidth, maxHidth);
    }


    /** 4.
     * 默認值,原始比例
     * @param url 地址
     * @param imageListener 圖片監聽
     */
    public static void Image_Loader(String url,ImageLoader.ImageListener imageListener){
        Volley_ImageLoader(url,imageListener,0,0);
    }


    /** 4.
     * 封裝 ImageLoader 方法
     * @param url 地址
     * @param imageListener 圖片監聽
     * @param maxWidth
     * @param maxHidth
     */
    private static void Volley_ImageLoader(String url,ImageLoader.ImageListener imageListener,int maxWidth,int maxHidth){
        // 設置 圖片緩存 :體現 imageLoader的優勢
        // 使用 LruBitmap + ImageCache 實現
        // 實例化對象
        ImageLoader imageLoader = new ImageLoader(MyApp.getQueue(),
                new VolleyBitmapCache());
        // 加載圖片 圖片監聽 (默認圖片,錯誤圖片) 和 imageView
        imageLoader.get(url, imageListener,maxWidth,maxHidth);
    }
    /**
     * 取消某個界面的網絡    請求
     * @param activity 請求所在的activity
     */
    public static void CancelAllRequest(Activity activity){
        MyApp.getQueue().cancelAll(activity);
    }
}

//上邊類中圖片內存緩存的工具類,在這一工具類中,我去掉了內存緩存

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.util.LruCache;
import com.android.volley.toolbox.ImageLoader.ImageCache;

@SuppressLint("NewApi")
public class VolleyBitmapCache implements ImageCache{
    //使用LruCache 實現圖片緩存 :
    private LruCache cache;
    //設置最大的 尺寸值

    public VolleyBitmapCache() {
        //構造方法 實現 LruCache 緩存 圖片
        int maxSize=10*1024*1024;
        cache=new LruCache(maxSize){
            @Override
            protected int sizeOf(String key, Bitmap value) {
                return value.getRowBytes()*value.getHeight();
            }
        };
    }

    @Override
    public Bitmap getBitmap(String url) {
        // 得到
        return cache.get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        // 設置
        cache.put(url, bitmap);
    }
}

未完待續。。。。。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved