一款集成了網絡請求,本地緩存,配置文件,數據庫映射,權限申請,鏈表管理Activity,簡化Activity、Service、Broadcast啓動, 萬能ListView,GridView適配器、高仿IOS彈窗、倒計時/延遲執行,標題欄組件,圖片顯示,webview引擎,APP更新組件,APP崩潰日誌組件,事件總線(熱更新組件暫未加入,有須要請聯繫)。java
項目地址:github.com/fanhua1994/…(給顆星星咯)android
目前最新版本是1.0.3 更新日誌git
簡書:www.jianshu.com/u/50c9e5f00…github
CSDN:blog.csdn.net/dong_183832…web
須要提交代碼的朋友請郵箱聯繫並附上代碼便可:90fanhua@gmail.comsql
在項目root gradle加入數據庫
allprojects {
repositories {
google()
jcenter()
//加入如下倉庫
maven { url 'https://jitpack.io' }
}
}
複製代碼
app下的gradle加入json
dependencies {
compile 'com.github.fanhua1994:XBaseAndroid:1.0.3'
}
複製代碼
<application
android:name="com.hengyi.baseandroidcore.base.XBaseApplication"
...
...
/>
複製代碼
因爲ButterKnife不能再lib中bind。因此必須繼承XBaseActivity進行二次封裝。XBaseAndroid不提供視圖註解,如需使用請自行引入如下庫。緩存
compile 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
複製代碼
package com.hengyi.baseandroiddemo;
import android.os.Bundle;
import com.hengyi.baseandroidcore.base.XBaseActivity;
import butterknife.ButterKnife;
import butterknife.Unbinder;
/**
* Created by Administrator on 2017/10/10.
*/
public abstract class BaseActivity extends XBaseActivity {
private Unbinder unbind = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
unbind = ButterKnife.bind(this);
}
@Override
public int setBaseContentView() {
return setContentView();
}
public abstract int setContentView();
@Override
protected void onDestroy() {
super.onDestroy();
unbind.unbind();
}
}
複製代碼
CustomAlertDialog dialog = new CustomAlertDialog(this).builder();
dialog.setTitle("舒適提示");
dialog.setMsg("你好啊");
dialog.show();
複製代碼
CustomAlertDialog dialog = new CustomAlertDialog(this).builder();
dialog.setTitle("舒適提示");
dialog.setMsg("你好啊");
dialog.setNegativeButton("肯定", new View.OnClickListener() {
@Override
public void onClick(View view) {
toast("點擊了肯定");
}
});
dialog.setPositiveButton("取消",null);
dialog.show();
複製代碼
CustomConfirmDialog dialog = new CustomConfirmDialog(this).builder();
dialog.setTitle("舒適提示");
dialog.setInputNumber(false);
dialog.setNegativeButton("取消", new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
dialog.setPositiveButton("取消",new CustomConfirmDialog.OnPostListener(){
@Override
public void OnPost(String value) {
toast(value);
}
});
dialog.show();
複製代碼
showLoadingDialog("正在加載");
closeLoadingDialog();
複製代碼
countdownUtils = CountdownUtils.getInstance();
countdownUtils.start(100000,1000);
countdownUtils.setCountdownListener(new CountdownUtils.setOnCountDownListener() {
@Override
public void onTick(int second) {
numberProgressBar.setProgress(100 - second);
}
@Override
public void onFinish() {
}
});
複製代碼
TimerUtils timer = TimerUtils.getInstance();
timer.setTimer_id(123);
timer.startTimer(5);//單位秒
timer.setTimerListener(new TimerUtils.TimerTaskCallbackListener() {
@Override
public void Timing(int timer_id, int timer_count) {
toast("timer_id:"+timer_id);
}
});
複製代碼
AndroidManifest.xmlbash
<uses-permission android:name="android.permission.READ_CONTACTS"></uses-permission>
複製代碼
PermissionUtils.requestPermissions(this,200,new String[]{"android.permission.READ_CONTACTS"},new PermissionUtils.OnPermissionListener(){
@Override
public void onPermissionGranted() {
toast("權限申請成功");
}
@Override
public void onPermissionDenied(String[] deniedPermissions) {
toast("權限申請失敗");
}
});
複製代碼
工做組就比如咱們將咱們的外部儲存分爲不少不少目錄,每一個目錄一個分組。文件互不影響。能夠刪除寫入數據。目前默認的有db、cache、file分組。其餘須要自定義。
boolean isok = ProjectUtils.getInstance().setIdCard(true).setFileType(FileUtil.CACHE_FILE).createWorkGroup("mycache12");
toast("執行結果:" + isok);
//setIdCard setFileType能夠不調用。默認是自定義分組模式,外部儲存有優先。
複製代碼
DiskLruCacheHelper cache = DiskLruCacheHelper.getInstance(this);
cache.put("cache","21424984034324934320434940494044904239");
toast(cache.getAsString("cache") +"緩存大小:"+cache.getCacheCount());
複製代碼
ConfigUtil自主維護了一個哈希表能夠很快的根據數據緩存拿到數據,不用去xml裏面讀取,性能很不錯。
ConfigUtils config = ConfigUtils.getInstance(this);
config.addOrUpdateText("name","繁華");
toast(config.findStringByKey("name"));
config.clearConfig();
複製代碼
<com.hengyi.baseandroidcore.weight.EaseTitleBar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
app:titleBarTitle="標題欄演示"
app:titleBarLeftImage="@drawable/icon_back"
android:layout_height="50dp">
</com.hengyi.baseandroidcore.weight.EaseTitleBar>
複製代碼
@BindView(R.id.titleBar)EaseTitleBar easeTitleBar;
easeTitleBar.setLeftLayoutClickListener(new View.OnClickListener(){
@Override
public void onClick(View view) {
ActivityStack.getInstance().popActivity();
}
});
複製代碼
ActivityStack.getInstance().popActivity();
千萬不要使用finish();
複製代碼
WebEngineActivity.java須要在Mainfast.xml註冊activity。最新修復web引擎支持隱藏標題欄。
StartActivity(WebEngineActivity.class,new String[]{WebEngineActivity.WEB_URL_PARAM,WebEngineActivity.WEB_SHOW_TITLE_BAR},"http://www.baidu.com/",false);
複製代碼
package com.hengyi.db;
import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;
/**
* Created by Administrator on 2017/10/8.
*/
@DatabaseTable
public class Student {
@DatabaseField
private int id;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
@DatabaseField
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
複製代碼
package com.hengyi.db;
import android.content.Context;
import com.hengyi.baseandroidcore.database.BaseDao;
import com.hengyi.baseandroidcore.database.BaseDaoImpl;
import java.sql.SQLException;
/**
* Created by Administrator on 2017/10/11.
*/
public class StudentDao {
private BaseDao<Student,Integer> studentDao;
public StudentDao(Context context){
studentDao = new BaseDaoImpl<>(context,Student.class);
}
public int add(Student s){
try {
return studentDao.save(s);
} catch (SQLException e) {
e.printStackTrace();
return 0;
}
}
}
複製代碼
DatabaseHelper.setDatabase("easy",2);//設置數據庫版本及名稱
DatabaseHelper.addTable(Student.class);
複製代碼
StudentDao sd = new StudentDao(context);
Student s = new Student();
s.setId(1);
s.setName("ggeegegerger");
int res = sd.add(s);
toast("添加學生結果是:" + res);
複製代碼
DatabaseHelper.getInstance(this).setDatabaseVersionChangeListener(new DatabaseVersionChangeListener() {
@Override
public void onChange(int oldVersion, int newVersion) {
toast("數據庫版本繁盛變化:老版本:"+oldVersion +" 新版本:"+newVersion);
if(newVersion == 2){
try {
DatabaseHelper.getInstance(getContext()).getDao(Student.class).executeRaw("ALTER TABLE 'student' ADD COLUMN sex int");
toast("數據更新成功");
} catch (SQLException e) {
e.printStackTrace();
toast("數據更新失敗");
}
}
}
});
toast("當前數據庫版本:"+DatabaseHelper.getInstance(this).getVersion() +"數據庫名:"+DatabaseHelper.getInstance(this).getDatabaseName());
複製代碼
StatusBarCompat.setStatusBarColor(Activity activity, int color)
StatusBarCompat.setStatusBarColor(Activity activity, int statusColor, int alpha)
StatusBarCompat.translucentStatusBar(activity);
//須要隱藏狀態欄背景須要SDK版本大於21
StatusBarCompat.translucentStatusBar(Activity activity, boolean hideStatusBarBackground);
setStatusBarColorForCollapsingToolbar(Activity activity, AppBarLayout appBarLayout, CollapsingToolbarLayout collapsingToolbarLayout,Toolbar toolbar, int statusColor)
複製代碼
本框架網絡請求使用的是OkGo框架,文檔地址以下網絡請求文檔猛戳查看
ActivityStack.getInstance().clearAllActivity();
kill();
複製代碼
表單校驗做爲重要的模塊,我獨立出來了,須要使用的請看詳解介紹咯。 參考文檔
若是您只須要接入校驗模塊,請參考這個地址:github.com/fanhua1994/…
application節點下添加
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.hengyi.XBaseandroid.fileProvider"//這個請替換爲你的軟件包名
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>
複製代碼
UpdateBean updateBean = new UpdateBean();
updateBean.setDescription("今日更新了XBaseAndroid框架的更新管理器。");
updateBean.setDownload_url("http://file.cleveriip.com:88/group2/M00/00/03/rBJbXVnlcPCATMAtAtnNwW8wwRs625.apk");
updateBean.setForce(true);//是否強制更新 或 靜默安裝
updateBean.setAuthority("com.hengyi.XBaseandroid.fileProvider");//兼容安卓7.0 安裝
updateBean.setMd5_code("a034366c2257281060a3ee27df38a793");
updateBean.setNew_version("1.0.0.1");
updateBean.setTitle("新版原本啦,當即更新吧");
AppUpdateManager appUpdateManager = AppUpdateManager.getInstance();
appUpdateManager.checkUpdate(updateBean,this);
appUpdateManager.setAppUpdateListener(new AppUpdateManager.AppUpdateListener() {
@Override
public void downloadProgressBar(String progress, String speed) {
Log.d("AppUpdateManager","進度條:" + progress +" 下載速度:" + speed);
}
@Override
public void downloadSuccess(File app_path) {
Log.d("AppUpdateManager","下載成功 路徑以下:" + app_path.getAbsolutePath());
}
@Override
public void downloadStart() {
Log.d("AppUpdateManager","下載開始");
}
@Override
public void downloadError(String message) {
Log.d("AppUpdateManager","下載錯誤");
}
@Override
public void downloadFinish() {
Log.d("AppUpdateManager","下載結束");
}
@Override
public void cancelDownload() {
Log.d("AppUpdateManager","取消下載");
}
@Override
public void NoUpdate() {
Log.d("AppUpdateManager","沒有更新");
}
});
複製代碼
:48:39.332 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:78.49 下載速度:789.25kb/s
11-12 05:48:39.645 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:79.43 下載速度:889.85kb/s
11-12 05:48:39.945 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:80.80 下載速度:1.03mb/s
11-12 05:48:40.250 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:82.20 下載速度:1.18mb/s
11-12 05:48:40.548 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:83.84 下載速度:1.37mb/s
11-12 05:48:41.186 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:85.09 下載速度:1.40mb/s
11-12 05:48:41.488 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:85.91 下載速度:1.45mb/s
11-12 05:48:41.791 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:86.79 下載速度:1.49mb/s
11-12 05:48:42.089 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:88.55 下載速度:1.66mb/s
11-12 05:48:42.440 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:89.74 下載速度:1.70mb/s
11-12 05:48:42.740 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:90.63 下載速度:1.71mb/s
11-12 05:48:43.046 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:91.54 下載速度:1.71mb/s
11-12 05:48:43.358 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:92.31 下載速度:1.61mb/s
11-12 05:48:43.663 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:93.06 下載速度:1.51mb/s
11-12 05:48:43.974 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:93.96 下載速度:1.40mb/s
11-12 05:48:44.309 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:94.55 下載速度:1.39mb/s
11-12 05:48:44.641 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:95.88 下載速度:1.44mb/s
11-12 05:48:45.027 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:96.70 下載速度:1.41mb/s
11-12 05:48:45.336 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:97.53 下載速度:1.27mb/s
11-12 05:48:45.638 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:98.34 下載速度:1.23mb/s
11-12 05:48:45.937 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:99.18 下載速度:1.23mb/s
11-12 05:48:46.243 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:99.93 下載速度:1.20mb/s
11-12 05:48:46.250 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 進度條:100.00 下載速度:1.35mb/s
11-12 05:48:46.253 9028-9028/com.hengyi.baseandroiddemo D/AppUpdateManager: 下載成功 路徑以下:/storage/emulated/0/Android/data/com.hengyi.baseandroiddemo/download/XBaseAndroid_軟件更新_1.0.0.1.apk
複製代碼
內容 | 原圖 | Luban |
Wechat |
---|---|---|---|
截屏 720P | 720*1280,390k | 720*1280,87k | 720*1280,56k |
截屏 1080P | 1080*1920,2.21M | 1080*1920,104k | 1080*1920,112k |
拍照 13M(4:3) | 3096*4128,3.12M | 1548*2064,141k | 1548*2064,147k |
拍照 9.6M(16:9) | 4128*2322,4.64M | 1032*581,97k | 1032*581,74k |
滾動截屏 | 1080*6433,1.56M | 1080*6433,351k | 1080*6433,482k |
Luban
內部採用IO
線程進行圖片壓縮,外部調用只需設置好結果監聽便可:
Luban.with(this)
.load(photos) // 傳人要壓縮的圖片列表
.ignoreBy(100) // 忽略不壓縮圖片的大小
.setTargetDir(getPath()) // 設置壓縮後文件存儲位置
.setCompressListener(new OnCompressListener() { //設置回調
@Override
public void onStart() {
// TODO 壓縮開始前調用,能夠在方法內啓動 loading UI
}
@Override
public void onSuccess(File file) {
// TODO 壓縮成功後調用,返回壓縮後的圖片文件
}
@Override
public void onError(Throwable e) {
// TODO 當壓縮過程出現問題時調用
}
}).launch(); //啓動壓縮
複製代碼
同步方法請儘可能避免在主線程調用以避免阻塞主線程,下面以rxJava調用爲例
Flowable.just(photos)
.observeOn(Schedulers.io())
.map(new Function<List<String>, List<File>>() {
@Override public List<File> apply(@NonNull List<String> list) throws Exception {
// 同步方法直接返回壓縮後的文件
return Luban.with(MainActivity.this).load(list).get();
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe();
複製代碼
NotifacationUtils notifacation = new NotifacationUtils(this);//實例化通知欄
notifacation.createProgressNotify(R.drawable.ic_launcher,200,"正在下載中","APP更新","App正在準備下載",new Intent());//建立進度條通知欄
notifacation.showProgressNotify(progress2,"當前下載網速" + speed);//設置進度條及文字顯示
//notifacation.createNotify();//建立普統統知欄
複製代碼
//使用時,註冊就好了
onCreate(){
EventBus.getDefault().register(this);
}
//界面銷燬時 反註冊
onDestroy(){
EventBus.getDefault().unregister(this);
}
複製代碼
@Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent(DefaultMessageEvent event) {/* Do something */};
複製代碼
如何發送消息?
EventManager.sendDefaultMessage(DefaultMessageEvent defaultMessageEvent);
複製代碼
DefaultMessageEvent是默認的消息類,您能夠自定義消息。但默認的支持擴展數據,徹底足夠使用。DefaultMessageEvent支持如下的數據格式。
private Object obj;//傳輸對象
private int code;//傳輸數字
private int status;
private int mint;
private int type;
private float mfloat;//傳輸單精度數字
private double mdouble;//傳輸雙精度數字
private long mlong;//傳輸長整型
private String content;//傳輸字符串
private Map<String,Object> map;//擴展包
複製代碼
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<com.hengyi.baseandroidcore.weight.NumberProgressBar
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/numberbar"
android:layout_width="wrap_content"
android:padding="20dp"
app:progress_current="0"
style="@style/NumberProgressBar_Default"
android:layout_height="wrap_content" />
</LinearLayout>
複製代碼
模擬進度條 採用倒計時控件
CountDownUtils countDownUtils = new CountDownUtils(100000,1000);
countDownUtils.start(new CountDownUtils.setOnCountDownListener() {
@Override
public void onTick(int second) {
numberProgressBar.setProgress(100 - second);
}
@Override
public void onFinish() {
}
});
複製代碼
ClipboardUtils.getInstance().copy(Context context,String text);//複製
ClipboardUtils.getInstance().paste(Context context)//黏貼
ClipboardUtils.getInstance().setListener(Context context,ClipboardManager.OnPrimaryClipChangedListener m_listener);
複製代碼
boolean status = NetworkUtils.isNetworkConnected(Context context);
複製代碼
源碼以下:
public static <T> T parseJsonWithGson(String jsonData, Class<T> type) {
if(gson == null)
gson = new Gson();
T result = gson.fromJson(jsonData, type);
return result;
}
複製代碼
使用以下:
User users = GsonUtils.parseJsonWithGson("{\"id\":1,\"name\":\"董志平\"}",User.class);
複製代碼
咱們編寫一個Adapter
package com.zhiweism.youerplatformparent.adapter;
import android.content.Context;
import android.view.View;
import com.hyphenate.chat.EMClient;
import com.hyphenate.exceptions.HyphenateException;
import com.zhiweism.youerplatformparent.R;
import com.zhiweism.youerplatformparent.table.FriendApply;
import com.zhiweism.youerplatformparent.table.FriendApplyDao;
import com.zhiweism.youerplatformparent.utils.GeneralUtils;
import java.util.List;
/**
* Created by Administrator on 2017/12/4.
*/
public class FriendApplyAdapter extends CommonAdapter<FriendApply> {
private Context context;
public FriendApplyAdapter(Context context, List<FriendApply> data, int layout_id) {
super(context, data, layout_id);
this.context = context;
}
@Override
public void ViewHolder(CommonViewHolder holder, int position) {
final FriendApply friendApply = getItem(position);
holder.setText(R.id.tv_username,friendApply.getUsername(),null);
holder.setText(R.id.tv_message,friendApply.getMessage(),null);
holder.setViewListener(R.id.refuse,new View.OnClickListener(){
@Override
public void onClick(View view) {
try {
EMClient.getInstance().contactManager().declineInvitation(friendApply.getUsername());
data.remove(friendApply);
FriendApplyDao.getInstance().remove(friendApply);
notifyDataSetChanged();
} catch (HyphenateException e) {
e.printStackTrace();
}
}
});
holder.setViewListener(R.id.pass,new View.OnClickListener(){
@Override
public void onClick(View view) {
try {
EMClient.getInstance().contactManager().acceptInvitation(friendApply.getUsername());
data.remove(friendApply);
FriendApplyDao.getInstance().remove(friendApply);
notifyDataSetChanged();
} catch (HyphenateException e) {
e.printStackTrace();
}
}
});
}
}
複製代碼
void setText(int layout_id,String text,View.OnClickListener listener);
複製代碼
void setImage(int layout_id,String image_url,View.OnClickListener listener)
複製代碼
void setCircleImage(int layout_id,String image_url,View.OnClickListener listener)
複製代碼
View getView(int layout_id)
複製代碼
<T> T getView(int layout_id,Class<T> type)
複製代碼
void setViewListener(int layout_id,View.OnClickListener listener)
複製代碼
我這裏只講如何的使用線程池,詳細請到demo中查看。下面建立100個線程。可是同時只會建立4個新的對象。當線程池空時,去隊列拿線程,直到建立的線程數量 + 1 = maxPoolSize就會中止建立。
//建立線程池 實際中執行的線程是比maxPoolSize少一個的。
HandlerExecutorPool handlerExecutorPool = HandlerExecutorPool.getInstance(5,200);
for(int i = 0;i < 100;i++){
LoginThread loginThread = new LoginThread();
Thread thread = new Thread(loginThread);
handlerExecutorPool.execute(thread);
}
複製代碼
//關閉線程池
handlerExecutorPool.stutdown();
複製代碼
修改colors.xml
<color name="main_color">#20a7e6</color>
複製代碼
StatusBarCompat.setStatusBarColor(this, Color.parseColor(ColorUtils.changeColor(this,R.color.main_color)));
複製代碼
package com.hengyi.adapter;
import android.bluetooth.BluetoothDevice;
import android.content.Context;
import com.hengyi.baseandroidcore.adapter.CommonAdapter;
import com.hengyi.baseandroidcore.adapter.CommonViewHolder;
import com.hengyi.baseandroiddemo.R;
import java.util.List;
/**
* Created by Administrator on 2017/11/22.
*/
public class BluetoothsAdapter extends CommonAdapter<BluetoothDevice> {
public BluetoothsAdapter(Context context, List<BluetoothDevice> data, int layout_id) {
super(context, data, layout_id);
}
private String getStatus(int status){
if(status == BluetoothDevice.BOND_BONDED){
return "已配對";
}else if(status == BluetoothDevice.BOND_BONDING){
return "配對中";
}else{
return "未配對";
}
}
@Override
public void ViewHolder(CommonViewHolder holder, int position) {
BluetoothDevice bluetoothDevice = getItem(position);
holder.setText(R.id.name,bluetoothDevice.getName(),null);
holder.setText(R.id.address,bluetoothDevice.getAddress(),null);
holder.setText(R.id.status,getStatus(bluetoothDevice.getBondState()),null);
}
}
複製代碼