RxPermissions mRxPermissions = new RxPermissions(this);
複製代碼
//連續獲取兩個權限以上
mRxPermissions
.requestEach(Manifest.permission.CALL_PHONE,
Manifest.permission.BLUETOOTH)
.subscribe(new Consumer<Permission>() {
@Override
public void accept(Permission permission) throws Exception {
if (permission.granted) {
// 獲取了權限
Toast.makeText(RxPermissionsActivity.this,
"獲取兩個權限",
Toast.LENGTH_SHORT).show();
} else if (permission.shouldShowRequestPermissionRationale) {
//沒有獲取權限,可是用戶沒有點不在詢問
Toast.makeText(RxPermissionsActivity.this,
"權限拒絕,可是沒有點不在詢問",
Toast.LENGTH_SHORT).show();
} else {
//用戶已經點了不在詢問,須要去啓動設置開啓權限
Toast.makeText(RxPermissionsActivity.this,
"權限拒絕,而且不能詢問",
Toast.LENGTH_SHORT).show();
}
}
},
new Consumer<Throwable>() {
@Override
public void accept(Throwable t) {
Timber.tag(getClassName()).i("發生異常" + t);
}
},
new Action() {
@Override
public void run() {
Timber.tag(getClassName()).i("完成");
}
});
複製代碼
RxPermissions
的使用,我在實際工程中,沒有使用過//使用RxView的簡單的例子
disposable = RxView.clicks(findViewById(R.id.enableCamera))
// 單擊按鈕時請求權限
.compose(mRxPermissions.ensureEach(Manifest.permission.CAMERA))
.subscribe(new Consumer<Permission>() {
@Override
public void accept(Permission permission) {
Timber.tag(getClassName()).i("Permission result " + permission);
if (permission.granted) {
releaseCamera();
camera = Camera.open(0);
try {
camera.setPreviewDisplay(surfaceView.getHolder());
camera.startPreview();
} catch (IOException e) {
Timber.tag(getClassName()).i("IOException result " + e);
}
} else if (permission.shouldShowRequestPermissionRationale) {
Toast.makeText(RxPermissionsActivity.this,
"權限拒絕,可是沒有點不在詢問",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(RxPermissionsActivity.this,
"用戶已經點了不在詢問,須要去啓動設置開啓權限",
Toast.LENGTH_SHORT).show();
}
}
},
new Consumer<Throwable>() {
@Override
public void accept(Throwable t) {
Timber.tag(getClassName()).i("發生異常" + t);
}
},
new Action() {
@Override
public void run() {
Timber.tag(getClassName()).i("完成");
}
});
複製代碼
buildTypes {
// timber 的配置 debuggable
release {
minifyEnabled false
debuggable false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
debug {
debuggable true
}
}
複製代碼
@Override
public void onCreate() {
super.onCreate();
if (BuildConfig.DEBUG) {
//也能夠設置log一直開
Timber.plant(new DebugTree());
} else {
//上線的話 就關閉有些沒必要要的日記輸出
Timber.plant(new CrashReportingTree());
}
QMUISwipeBackActivityManager.init(this);
//打印tag爲類名
Timber.v("---HementApplication ---");
}
複製代碼
private static final class CrashReportingTree extends Timber.Tree {
@Override
protected boolean isLoggable(@Nullable String tag, int priority) {
return priority >=INFO;
}
@Override
protected void log(int priority, @org.jetbrains.annotations.Nullable String tag, @NotNull String message, @org.jetbrains.annotations.Nullable Throwable t) {
if (priority == Log.VERBOSE || priority == Log.DEBUG) {
return;
}
FakeCrashLibrary.log(priority, tag, message);
if (t != null) {
if (priority == Log.ERROR) {
FakeCrashLibrary.logError(t);
} else if (priority == Log.WARN) {
FakeCrashLibrary.logWarning(t);
}
}
}
}
複製代碼
我我的對Timber的理解就是 很是的簡單,也很是的方便控制那些日誌上線和Debug中不能夠輸出,雖然咱們本身也能夠作到,可是Timer還有個其餘的功能,能夠和 %d
%s
一塊兒使用java
%d
後面接上Long Int等類型 %s
後面接上字符串類型,在Hement的項目中,我是這樣封裝使用的android
在BaseActivity 中獲取這個類名git
protected String getClassName(){
return this.getClass().getSimpleName();
}
複製代碼
Timber.tag(getClassName()).i("建立新的configPersistentComponent id=%d",mActivityId);
Timber.tag(getClassName()).i("mMainPresenter =%s",mMainPresenter);
複製代碼
sqlbrite
對 Android
系統的SQLiteOpenHelper
和 ContentResolver
的輕量級封裝,配合Rxjava2
使用。sqlbrite
,完美解決數據庫和UI
的同步更新!// 數據庫
api 'com.squareup.sqlbrite3:sqlbrite:3.2.0'
複製代碼
public class DB {
public DB() { }
public abstract static class HementTable {
public static final String TABLE_NAME = "hement";
public static final String COLUMN_TITLE = "title";
public static final String COLUMN_DATE = "date";
public static final String COLUMN_DAY = "day";
// 注意建立表的結構是否正確
public static final String CREATE =
"CREATE TABLE " + TABLE_NAME + " (" +
COLUMN_TITLE + " TEXT NOT NULL, " +
COLUMN_DATE + " TEXT NOT NULL, " +
COLUMN_DAY + " TEXT NOT NULL" +
" ); ";
public static ContentValues toContentValues(TodayBean ribot) {
ContentValues values = new ContentValues();
values.put(COLUMN_TITLE, ribot.title);
values.put(COLUMN_DATE, ribot.date);
values.put(COLUMN_DAY, ribot.day);
return values;
}
public static TodayBean parseCursor(Cursor cursor) {
String title = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_TITLE));
String date = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DATE));
String day = cursor.getString(cursor.getColumnIndexOrThrow(COLUMN_DAY));
TodayBean bean = new TodayBean();
bean.setDate(date);
bean.setTitle(title);
bean.setDay(day);
return bean;
}
}
複製代碼
ContentValues
:該類用於存儲處理的一組值,底層原理就是HashMap。ContentResolver
可以去處理,等於他們結合使用@Singleton
public class DbOpenHelper extends SQLiteOpenHelper {
public static final String DATABASE_NAME = "hement.db";
public static final int DATABASE_VERSION = 1;
@Inject
public DbOpenHelper(@ApplicationContext Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onConfigure(SQLiteDatabase db) {
super.onConfigure(db);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.beginTransaction();
try {
db.execSQL(DB.HementTable.CREATE);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }
複製代碼
@Singleton
public class DatabaseHelper {
private final BriteDatabase mDb;
@Inject
public DatabaseHelper(DbOpenHelper dbOpenHelper) {
this(dbOpenHelper, Schedulers.io());
}
public DatabaseHelper(DbOpenHelper dbOpenHelper, Scheduler scheduler) {
SqlBrite.Builder briteBuilder = new SqlBrite.Builder();
mDb = briteBuilder.build().wrapDatabaseHelper(dbOpenHelper, scheduler);
}
public BriteDatabase getDb() {
return mDb;
}
/**
* 保存數據庫中的數據,這個數據的來源是網絡請求
* @param newRibots
* @return
*/
public Observable<TodayBean> setDBData(final List<TodayBean> newRibots) {
return Observable.create(new ObservableOnSubscribe<TodayBean>() {
@Override
public void subscribe(ObservableEmitter<TodayBean> emitter) throws Exception {
if (emitter.isDisposed()) return;
BriteDatabase.Transaction transaction = mDb.newTransaction();
try {
mDb.delete(DB.HementTable.TABLE_NAME, null);
for (TodayBean ribot : newRibots) {
long result = mDb.insert(DB.HementTable.TABLE_NAME,
DB.HementTable.toContentValues(ribot),
SQLiteDatabase.CONFLICT_REPLACE);
if (result >= 0) emitter.onNext(ribot);
}
transaction.markSuccessful();
emitter.onComplete();
} finally {
transaction.end();
}
}
});
}
/**
* 獲取數據庫中的數據
* @return
*/
public Observable<List<TodayBean>> getDBData() {
return mDb.createQuery(DB.HementTable.TABLE_NAME,
"SELECT * FROM " + DB.HementTable.TABLE_NAME)
.mapToList(new Function<Cursor, TodayBean>() {
@Override
public TodayBean apply(@NonNull Cursor cursor) throws Exception {
return DB.HementTable.parseCursor(cursor);
}
});
}
}
複製代碼
retrofit converter-gson adapter-rxjava2 rxandroid rxjava logging-interceptorgithub
QMUI Android
的設計目的是用於輔助快速搭建一個具有基本設計還原效果的Android
項目,同時利用自身提供的豐富控件及兼容處理,讓開發者能專一於業務需求而無需耗費精力在基礎代碼的設計上。不論是新項目的建立,或是已有項目的維護,都可使開發效率和項目質量獲得大幅度提高。sql
功能特性數據庫
在此感謝QMUI的小夥伴無私貢獻api
未完待續 下一篇文章bash
GitHub地址:Hement:持續更新中網絡
因爲使用Dagger2的未知性,因此建立一個分支沒有使用Dagger2 Hement架構
感謝一下博客對個人幫助