編輯:關於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);
}
}
未完待續。。。。。
MediaPlayer 其實這個類就是用於播放音頻或者視頻的,那今天就學習學習這個類,這幅圖非常好,讓我偷來了,O(∩_∩)O哈哈~1 --MediaPl
介紹圓角控件常用於頭像,按鈕,圖標等,用途十分廣泛,而且常常配合board使用。在IOS中,UIVIew的CALayer層已經提供了圓角和board的方法,所以圓角控件的
在閻宏博士的《JAVA與模式》一書中開頭是這樣描述觀察者(Observer)模式的: 觀察者模式是對象的行為模式,又叫發布-訂閱(Publish/Subscribe
Android的消息機制主要是指Handler的運行機制,Handler的運行需要底層的MessageQueue和Looper的支撐。MessageQueue 消息隊列,