Collection聚合了專案搭建的一些基本模組,節約開發者時間,協助專案的快速搭建,RecyclerView+Adapter+Retrofit+RxJava+MVP+DataManager+基本Base,能夠滿足一個專案的基本實現。
推薦檔案
Android X庫之前版本可使用Collection-Android:juejin.im/post/5ab998…
Collection-iOS庫:juejin.im/post/5e423d…
Collection-kotlin作為Collection-Android的更新篇,主要是為了解決使用Android X庫帶來的一些問題以及模組的優化
github地址:github.com/usernameyan…
簡書地址:www.jianshu.com/p/a6cb49532…
更新說明
v1.1.0
1.修復SQLite沒有建立表查詢異常 2.SQLite增加按條件查詢List 3.增加PopupWindow顯示位置設定 4.解決SQLit內容為null報錯
v1.0.1
狀態列修改:增加設定狀態列透明+黑色字型
v1.0.0
1.在Collection-Android的基礎上適配Android X庫
2.去掉Relam資料模組,安裝包大小減少
3.對原生SQLite資料庫進行封裝,使用更加方便 4.對DataManager的使用進行修整 5.增加AutoLineLayout/TagView 6.增加LinkedMultiValueMap
7.增加RxJavaUtils,可進行子/主執行緒資料處理切換
框架的引入
implementation 'com.youngman:collection_kotlin:1.1.0'
一、框架整體模組
二、PullToRefreshRecyclerView的使用
屬性 | 作用 |
---|---|
addHeaderView | 增加頭部佈局, 暫時只能新增一個頭佈局 |
setEmptyView | 設定自定義的載入佈局和空佈局 |
setRefreshView | 自定義重新整理View |
setDefaultLoadingMoreNoDataMessage | 設定預設沒有資料的內容 |
setLoadMoreView | 自定義載入更多View |
setNoMoreDate | 顯示沒有更多資料 |
setAutoRefresh | 自動重新整理 |
refreshComplete | 重新整理資料完成 |
loadMoreComplete | 載入更多資料完成 |
setPullRefreshEnabled | 是否允許重新整理 |
setLoadMoreEnabled | 是否允許載入更多 |
setRefreshTimeVisible | 顯示載入更新時間 |
isLoading | 是否正在loading資料 |
isRefreshing | 正在refreshing資料 |
setRefreshAndLoadMoreListener | 重新整理和載入更多回撥 |
destroy | 記憶體回收 |
1.框架預設下拉重新整理、上拉載入更多樣式
(1)佈局檔案
<com.youngmanster.collection_kotlin.recyclerview.PullToRefreshRecyclerView
android:id="@+id/recycler_rv"
android:layout_width="match_parent"
android:layout_height="match_parent" />
複製程式碼
(2)程式碼設定
recycler_rv.setPullRefreshEnabled(true)
recycler_rv.setLoadMoreEnabled(true)
複製程式碼
2、自定義下拉重新整理、上拉載入更多樣式
重新整理幾種狀態:
屬性 | 作用 |
---|---|
STATE_PULL_DOWN | 拉的狀態(還沒到下拉到固定的高度時) |
STATE_RELEASE_REFRESH | 下拉到固定高度提示釋放重新整理的狀態 |
STATE_REFRESHING | 正在重新整理狀態 |
STATE_DONE | 重新整理完成 |
載入更多幾種狀態:
屬性 | 作用 |
---|---|
STATE_LOADING | 正在載入 |
STATE_COMPLETE | 加 載完成 |
STATE_NODATA | 沒有資料 |
(1)程式碼設定
recycler_rv.setPullRefreshEnabled(true)
recycler_rv.setLoadMoreEnabled(true)
recycler_rv.setRefreshAndLoadMoreListener(this)
recycler_rv.setRefreshView(DefinitionAnimationRefreshHeaderView(activity))
recycler_rv.setLoadMoreView(DefinitionAnimationLoadMoreView(activity))
複製程式碼
自定義重新整理的步驟:
①自定義View繼承BasePullToRefreshView,重寫initView()、setRefreshTimeVisible(boolean show)、destroy()方法:
1.在initView()做自定義佈局、相關動畫的初始化,最後在initView()方法的最後面新增以下程式碼即可。
mContainer =
LayoutInflater.from(context).inflate(R.layout.layout_definition_animation_refresh, null)
//把重新整理頭部的高度初始化為0
val lp = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
lp.setMargins(0, 0, 0, 0)
this.layoutParams = lp
this.setPadding(0, 0, 0, 0)
addView(mContainer, LayoutParams(LayoutParams.MATCH_PARENT, 0))
gravity = Gravity.BOTTOM
//測量高度
measure(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
mMeasuredHeight = measuredHeight
複製程式碼
2.setRefreshTimeVisible(boolean show)是用來設定是否顯示重新整理時間控制元件,在預設重新整理樣式中通過mRecyclerView.setRefreshTimeVisible(false)即可隱藏重新整理時間,如果在自定義的佈局中沒有這項這個方法就可以忽略。
3.destroy()是用來關掉改頁面時把重新整理View的一些動畫等釋放,防止記憶體洩漏。
②實現BasePullToRefreshView.OnStateChangeListener監聽(重點,主要是進行狀態切換後的相關操作邏輯)
1.在建構函式中設定 onStateChangeListener=this 2.onStateChange的模板樣式
override fun onStateChange(state: Int) {
if(isDestroy){
return
}
//下拉時狀態相同不做繼續保持原有的狀態
if (state == mState) return
//根據狀態進行動畫顯示
when (state) {
STATE_PULL_DOWN -> {
clearAnim()
startAnim()
}
STATE_RELEASE_REFRESH -> {
}
STATE_REFRESHING -> {
clearAnim()
startAnim()
scrollTo(mMeasuredHeight)
}
STATE_DONE -> {
}
}
mState = state
}
複製程式碼
自定義載入更多的步驟(包括沒有更多資料顯示的操作):
①自定義View繼承BaseLoadMoreView,重寫initView()、setState()、destroy()方法:
1.在initView()做自定義佈局、相關動畫的初始化,最後在initView()方法的最後面新增以下程式碼即可
mContainer = LayoutInflater.from(context)
.inflate(R.layout.layout_definition_animation_loading_more, null)
addView(mContainer)
gravity = Gravity.CENTER
複製程式碼
2.destroy()是用來關掉改頁面時把重新整理View的一些動畫等釋放,防止記憶體洩漏。 3.在setState()進行狀態切換後的相關操作邏輯,模板樣式
override fun setState(state: Int) {
if(isDestroy){
return
}
when (state) {
STATE_LOADING -> {
loadMore_Ll?.visibility = VISIBLE
noDataTv?.visibility = INVISIBLE
animationDrawable = loadingIv?.drawable as AnimationDrawable
animationDrawable?.start()
this.visibility = VISIBLE
}
STATE_COMPLETE -> {
animationDrawable?.stop()
this.visibility = GONE
}
STATE_NODATA -> {
loadMore_Ll?.visibility = INVISIBLE
noDataTv?.visibility = VISIBLE
animationDrawable = loadingIv?.drawable as AnimationDrawable
animationDrawable?.start()
this.visibility = VISIBLE
}
}
mState = state
}
複製程式碼
4.注意:在自定義載入更多樣式時,如果需要有沒有更多載入更多資料提示同樣需要在佈局中寫好,然後在onSatae中根據狀態對載入和沒有跟多顯示提示進行顯示隱藏操作。
3、上拉載入更多配合SwipeRefreshLayout使用
(1)佈局檔案
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.youngmanster.collection_kotlin.recyclerview.PullToRefreshRecyclerView
android:id="@+id/recycler_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
複製程式碼
(2)程式碼設定
recycler_rv.setLoadMoreEnabled(true)
recycler_rv.setRefreshAndLoadMoreListener(this)
recycler_rv.setLoadMoreView(DefinitionAnimationLoadMoreView(activity))
swipeRefreshLayout.setColorSchemeResources(R.color.colorAccent)
swipeRefreshLayout.setOnRefreshListener(this)
複製程式碼
(3)注意的問題
由於PullToRefreshRecyclerView的下拉重新整理和下拉載入更多完成時會自動重新整理Adapter,而SwipeRefreshLayout重新整理完成時需要手動進行notifyDataSetChanged重新整理介面卡。
4、RecyclerView新增頭部、空佈局
(1)程式碼設定
//增加頭佈局
val header = LayoutInflater.from(activity).inflate(R.layout.layout_main_header, null)
recycler_rv.addHeaderView(header)
//增加空佈局
val emptyView = LayoutInflater.from(activity).inflate(R.layout.layout_empty, null)
recycler_rv.emptyView = emptyView
emptyView.setOnClickListener {
for (i in 0..9) {
mDatas.add("item$i")
}
definitionRefreshAdapter?.notifyDataSetChanged()
}
複製程式碼
5、上拉載入更多實現NoMoreData、自動重新整理
(1)上拉載入更多資料的佈局設定在上面的自定義LoadingMoreView中有介紹,如果要顯示沒有更多資料提示只需要在LoadMore返回資料之後設定:
mRecyclerView.setNoMoreDate(true)
複製程式碼
(2)自動重新整理需要列表已經填充了資料之後再做自動重新整理操作才會生效:
mRecyclerView.setAutoRefresh()
複製程式碼
6.Collection庫的重新整理載入文字已經適配了中文、英文、繁體,如果對預設重新整理載入顯示文字進行修改,通過LoadingTextConfig設定,可在Application全域性設定
val textConfig = LoadingTextConfig.getInstance(applicationContext)
textConfig
.setCollectionLoadingMore("載入更多")
.setCollectionLastRefreshTimeTip("更新時間:")
.setCollectionNoMoreData("沒有更多資料")
.setCollectionPullReleaseText("釋放重新整理")
.setCollectionRefreshing("正在重新整理")
.setCollectionPullDownRefreshText("下拉重新整理")
.setCollectionRefreshDone("載入完成")
PullToRefreshRecyclerViewUtils.loadingTextConfig = textConfig
複製程式碼
7、PullToRefreshRecyclerView的其他使用以及注意問題
1.下面是下拉重新整理上拉載入更多的一些操作模板
private fun refreshUI() {
if (defaultRefreshAdapter == null) {
defaultRefreshAdapter =
DefaultRecyclerAdapter(
activity!!,
R.layout.item_pull_refresh,
mDatas,
recycler_rv
)
recycler_rv.adapter = defaultRefreshAdapter
} else {
if (recycler_rv != null) {
if (recycler_rv.isLoading) {
recycler_rv.loadMoreComplete()
} else if (recycler_rv.isRefreshing) {
recycler_rv.refreshComplete()
}
}
}
}
複製程式碼
2.注意問題
①在設定RecyclerView是要設LayoutManager
②如果使用PullToRefreshRecyclerView在Activty/Fragment中的onDestroy()呼叫mRecyclerView.destroy()防止記憶體洩漏。
@Override
public void onDestroy() {
super.onDestroy();
mRecyclerView?.destroy()
}
複製程式碼
③設定refreshRv.setLoadMoreEnabled(true),當填充的資料的列表size為0的同時還通過RecyclerView設定分割線底部就會出現一個空白的item,這個item就是載入更多顯示的Item。
解決辦法:不通過RecyclerView設定分割線,直接在佈局自定義分割線。
三、BaseRecyclerViewAdapter的使用
1.BaseRecyclerViewAdapter的比原始Adapter的程式碼量減小
在BaseRecyclerViewAdapter中的BaseViewHolder進行佈局轉化,同時定義了一些比較基本的View操作,使用簡單。
(1)使用程式碼:
class DefinitionRecyclerAdapter(
mContext: Context,
mLayoutResId: Int,
mDatas: ArrayList<String>,
pullToRefreshRecyclerView: PullToRefreshRecyclerView
) : BaseRecyclerViewAdapter<String>(mContext, mLayoutResId, mDatas, pullToRefreshRecyclerView) {
override fun convert(baseViewHolder: BaseViewHolder, t: String) {
baseViewHolder.setText(R.id.title, t)
}
}
複製程式碼
①使用者需要在繼承BaseRecyclerViewAdapter時傳入一個資料實體型別,具體的操作在convert()方法中操作。
②BaseViewHolder提供了一些常用View的基本操作,通過baseViewHolder.getView()可得到佈局中的控制元件。
(2)BaseRecyclerViewAdapter提供了兩個建構函式
public BaseRecyclerViewAdapter(Context mContext, int mLayoutResId, List<T> mDatas, PullToRefreshRecyclerView pullToRefreshRecyclerView) {
this.mContext = mContext;
this.mLayoutResId = mLayoutResId;
this.mDatas = mDatas;
this.mRecyclerView=pullToRefreshRecyclerView;
}
public BaseRecyclerViewAdapter(Context mContext, int mLayoutResId, List<T> mDatas) {
this.mContext = mContext;
this.mLayoutResId = mLayoutResId;
this.mDatas = mDatas;
}
複製程式碼
主要是對PullToRefreshRecyclerView和RecyclerView的適配,使用時介面卡根據需要使用對應的建構函式。
2.新增Item的點選和長按事件
(1)Item長按事件實現
itemClickAdapter.setOnItemLongClickListener(object :
BaseRecyclerViewAdapter.onItemLongClickListener {
override fun onItemLongClick(view: View, position: Int): Boolean {
showToast("進行長按操作")
return true
}
})
複製程式碼
3.多佈局的使用
BaseRecyclerViewAdapter的多佈局實現需要注意的四步:
①自定義Adapter需要繼承BaseRecyclerViewMultiItemAdapter。
② 資料實體類需要繼承BaseMultiItemEntity,在getItemViewType()返回佈局型別。
③ 在自定義Adapter中的建構函式中通過addItemType()傳入不同型別對應的佈局。
④在自定義Adapter中的convert進行型別判斷,做相對應的操作。
class MultipleAdapter(mContext: Context, mDatas: ArrayList<MultiItem>) :
BaseRecyclerViewMultiItemAdapter<MultiItem>(mContext, mDatas) {
private var mHeight: Int=0
init {
mHeight = DisplayUtils.dip2px(mContext, 100f)
addItemType(MultiItem.TYPE_TEXT, R.layout.item_main)
addItemType(MultiItem.TYPE_IMG, R.layout.item_img)
addItemType(MultiItem.TYPE_TEXT_IMG, R.layout.item_click)
}
override fun convert(baseViewHolder: BaseViewHolder, t: MultiItem) {
when (baseViewHolder.itemViewType) {
MultiItem.TYPE_TEXT -> {
baseViewHolder.getView<CardView>(R.id.card_view).layoutParams.height = mHeight
baseViewHolder.setText(R.id.title, t.title)
}
MultiItem.TYPE_IMG -> baseViewHolder.setImageResource(R.id.ivImg, t.res)
MultiItem.TYPE_TEXT_IMG -> {
baseViewHolder.setImageResource(R.id.ivImg, t.res)
baseViewHolder.setText(R.id.titleTv, t.title)
}
}
}
}
複製程式碼
4.新增拖拽、滑動刪除
侷限:只針對RecyclerView,對本框架封裝的PullToRefreshRecyclerView會出現混亂。
①BaseRecyclerViewAdapter和BaseRecyclerViewMultiItemAdapter都已經封裝支援拖拽、滑動,介面卡只需要根據需求繼承其中一個即可。
②框架提供了一個BaseRecycleItemTouchHelper,對於普通的左右滑動刪除、拖拽已經實現,如果想自定義可以繼承BaseRecycleItemTouchHelper類,再重寫相對應的方法進行實現。
④在Activity/Fragment中需要實現以下程式碼:
dragAndDeleteAdapter?.setDragAndDeleteListener(this)
recycler_rv.adapter = dragAndDeleteAdapter
val callback = BaseRecycleItemTouchHelper(dragAndDeleteAdapter)
val itemTouchHelper = ItemTouchHelper(callback)
itemTouchHelper.attachToRecyclerView(recycler_rv)
複製程式碼
⑤BaseRecyclerViewAdapter.OnDragAndDeleteListener進行操作動作完成之後的回撥。
override fun onMoveComplete() {
ToastUtils.showToast(this, "移動操作完成")
}
override fun onDeleteComplete() {
ToastUtils.showToast(this, "刪除操作完成")
}
複製程式碼
四、MVP+RxJava+Retrofit的封裝使用
1.在使用Retrofit請求網路之前需要進行配置,在框架中提供了了Config配置類
屬性 | 作用 |
---|---|
DEBUG | 是否為BuildConfig.DEBUG,日誌輸出需要 |
CONTEXT | 設定Context,必填項 |
URL_DOMAIN | 網路請求的域名,需要以“/”結尾 |
URL_CACHE | 網路快取地址,需要設定快取才可以成功 |
MAX_CACHE_SECONDS | 設定OkHttp的快取機制的最大快取時間,預設為一天 |
MAX_MEMORY_SIZE | 快取最大的記憶體,預設為10M |
MClASS | 設定網路請求json通用解析類 |
EXPOSEPARAM | Json資料某些欄位在沒有資料是會不返回來,可通過這個屬性設定過濾 |
USER_CONFIG | SharePreference儲存的名稱 |
CONNECT_TIMEOUT_SECONDS | 請求介面超時設定 |
READ_TIMEOUT_SECONDS | 請求介面超時設定 |
HEADERS | 設定Http全域性請求頭 |
SQLITE_DB_NAME | 資料庫名稱 |
SQLITE_DB_VERSION | 資料庫版本名 |
在專案中需要根據專案需要進行配置,在Application中設定
private fun config(){
//基本配置
Config.DEBUG = BuildConfig.DEBUG
Config.CONTEXT = this
Config.URL_CACHE = AppConfig.getURLCacheDir(this)
Config.MClASS=HttpResult::class.java
Config.USER_CONFIG = "Collection_User"
Config.URL_DOMAIN = "https://api.apiopen.top/"
Config.SQLITE_DB_VERSION=0
}
複製程式碼
根據專案需要定義一個通用的資料實體類,這是本例通用實體類,這個類需要設定到Applicatin中
class HttpResult<T> : Serializable {
var code: Int = 0
var message: String? = null
var result: T? = null
}
複製程式碼
注意:由於每個專案返回來的json資料格式有所不同,如果Result中代表的欄位例如newslist沒有內容返回來的時候這個欄位需要後臺控制不返回,如果不做處理會報解析錯誤,可以通過設定Config.EXPOSEPARAM屬性過濾欄位。
2.RxJava+Retrofit+OkHttp
(1)RequestBuilder的設定(網路請求的配置)
屬性 | 作用 |
---|---|
ReqType | 資料處理的方式,預設DEFAULT_CACHE_LIST,使用到OkHttp快取的需要需要設定Config.URL_CACHE |
NO_CACHE_MODEL | 不設定快取,返回model |
NO_CACHE_LIST | 不設定快取,返回list |
DEFAULT_CACHE_MODEL | 使用Okttp預設快取,返回model |
DEFAULT_CACHE_LIST | 使用Okttp預設快取,返回list |
DISK_CACHE_LIST_LIMIT_TIME | 限時使用自定義磁碟快取,返回List |
DISK_CACHE_MODEL_LIMIT_TIME | 限時使用自定義磁碟快取,返回model |
DISK_CACHE_NO_NETWORK_LIST | 自定義磁碟快取,沒有網路返回磁碟快取,返回List |
DISK_CACHE_NO_NETWORK_MODEL | /自定義磁碟快取,沒有網路返回磁碟快取,返回Model |
HttpType | 網路請求方式,預設DEFAULT_GET |
DEFAULT_GET | GET請求 |
DEFAULT_POST | POST請求 |
FIELDMAP_POST | 如果請求URL出現中文亂碼,可選擇這個 |
JSON_PARAM_POST | json格式請求引數 |
ONE_MULTIPART_POST | 上傳一張圖片 |
MULTIPLE_MULTIPART_POST | 上傳多張圖片 |
ReqMode | 請求模式,預設ASYNCHRONOUS |
ASYNCHRONOUS | 非同步請求 |
SYNCHRONIZATION | 同步請求 |
其它引數 | |
setTransformClass | 設定請求轉化Class |
setUrl | 設定請求url,如果不設定完全連線則會使用Config.URL_DOMIN進行拼接 |
setFilePathAndFileName | 設定自定義快取時的路徑和檔名 |
setLimtHours | 設定自定義快取的有效時間 |
setHeader | 設定請求頭 |
setHeaders | 設定請求頭集合 |
setHttpTypeAndReqType | 設定請求資料型別和請求方式 |
setImagePath | 設定上傳圖片路徑 |
setImagePaths | 設定多張圖片路徑 |
isUserCommonClass | 設定是否使用公用類轉化 |
setReqMode | 設定同步非同步 |
(2)使用模組
val requestBuilder=RequestBuilder(object :RxObservableListener<HttpResult<List<WeChatNews>>>(mView){
override fun onNext(result: HttpResult<List<WeChatNews>>) {
mView?.refreshUI(result.result)
}
})
requestBuilder
.setUrl(ApiUrl.URL_WETCHAT_FEATURED)
.setTransformClass(WeChatNews().javaClass)
.setHttpTypeAndReqType(RequestBuilder.HttpType.DEFAULT_GET,RequestBuilder.ReqType.NO_CACHE_LIST)
.setParam("page",page)
.setParam("type","video")
.setParam("count",num)
rxManager.addObserver(DataManager.DataForHttp.httpRequest(requestBuilder))
複製程式碼
注意:
(1)RxObservableListener有三個回撥方法
void onNext(T result);
void onComplete();
void onError(NetWorkCodeException.ResponseThrowable e);
複製程式碼
只會重寫onNext方法,其它兩個方法可以自行選擇重寫。
(2)RxObservableListener提供兩個建構函式
protected RxObservableListener(BaseView view){
this.mView = view;
}
protected RxObservableListener(BaseView view, String errorMsg){
this.mView = view;
this.mErrorMsg = errorMsg;
}
複製程式碼
這兩個建構函式主要主要是為了統一處理onError的,如果要自定義錯誤提醒,則可以選擇第二個建構函式。
(3)通過DataManager的網路請求方式會返回來一個DisposableObserver,需要把它通過rxManager.addObserver()新增進CompositeDisposable才能正常執行,方便對網路請求的銷燬管理。
(4)如果專案沒有統一的解析been類,那麼Config的公用類就不用設定了,在Retrofit請求的時候直接setTransformClass指定一個解析類就可以了
(5)如果專案想兩種方式共存,那麼在請求的時候需要通過setUserCommonClass(false)設定才能不使用統一解析類進行解析
3.MVP
1.寫一個Contract類對Presenter和View進行統一管理(View需要實現BaseView,Presenter需要實現BasePresenter<T:BaseView>)
interface WeChatChinaNewsContract {
interface View : BaseView {
fun refreshUI(weChatNews: List<WeChatNews>?)
}
abstract class Presenter : BasePresenter<View>() {
abstract fun requestChinaNews(context: Context, page: Int, num: Int)
}
}
複製程式碼
2.寫一個具體的Presenter類實現WeChatChinaNewsContract.Presenter,在裡面做具體的邏輯處理,處理完成再通過mView進行View的處理
3.Activity/Fragment實現IBaseActivity<T:BasePresenter>/IBaseFragment<T:BasePresenter>以及定義好的WeChatChinaNewsContract.View
4.缺陷:View在使用時需要轉化成在具體的子類才能呼叫相關方法。
5.具體使用可以參照demo
五、DataManager的使用(Http、Sharepreference、SQLite)
(1)DataManager基本屬性
屬性 | 作用 |
---|---|
DataForSqlite | 資料庫模組 |
insert | 插入bean資料 |
insertList | 插入List資料 |
insertListBySync | 非同步插入List資料 |
queryByFirstByWhere | 根據條件查詢 |
queryAll | 查詢某個bean類的全部資料 |
queryAllBySync | 非同步查詢某個bean類的全部資料 |
queryByFirst | 查詢某個bean類的第一條資料 |
delete | 根據條件刪除資料 |
deleteAll | 刪除某個bean類的所有資料 |
deleteTable | 刪除資料表 |
update | 更新某個bean類的 |
queryOfPageByWhere | 根據條件分頁查詢,實體類必須包含PrimaryKey |
queryOfPage | 分頁查詢,實體類必須包含PrimaryKey |
updateTable | 更新資料表,用於增加欄位 |
execQuerySQL | Sql語句查詢 |
DataForHttp | Http模組 |
httpRequest | 網路請求,傳入RequestBuilder |
DataForSharePreferences | SharePreference模組 |
saveObject | 儲存基本型別資料 |
getObject | 獲取基本型別資料 |
(2)DataForSqlite
1.插入一條資料
var user= User()
user.id=0
user.age=24
user.name="張三"
var isSuccess=DataManager.DataForSqlite.insert(user)
if(isSuccess!!){
ToastUtils.showToast(activity,"儲存成功")
}else{
ToastUtils.showToast(activity,"儲存失敗")
}
複製程式碼
2.查詢資料
val user=DataManager.DataForSqlite.queryByFirst(User().javaClass)
ToastUtils.showToast(activity,"姓名:"+user?.name+" "+"年齡:"+user?.age)
複製程式碼
3.批量插入資料(可同步可非同步)
var list=ArrayList<User>()
for (i in 0..10000){
var user= User()
user.id=i
user.age=i
user.name="張$i"
list.add(user)
}
DataManager.DataForSqlite.insertListBySync(User().javaClass,list,object :SQLiteDataBase.InsertDataCompleteListener{
override fun onInsertDataComplete(isInsert: Boolean?) {
if(isInsert!!){
ToastUtils.showToast(activity,"儲存成功")
}else{
ToastUtils.showToast(activity,"儲存失敗")
}
}
})
複製程式碼
4.bean類的定義
class User{
@Column(isPrimaryKey = true)
var id:Int=0
var name:String?="你好"
var age:Int?=0
}
複製程式碼
其中可以通過Column進行註解定義(isPrimaryKey、isNull、isUnique)
5.資料表格變化(只支援增加欄位)
-
修改資料庫版本號Config.SQLITE_DB_VERSION,往上遞增
-
在Application中對版本號進行監聽,並對資料表進行更新
SQLiteVersionMigrate().setMigrateListener(object :SQLiteVersionMigrate.MigrateListener{ override fun onMigrate(oldVersion: Int, newVersion: Int) { for (i in oldVersion..newVersion){ if(i==2){ }
} } }) 複製程式碼
(3)DataForHttp
val requestBuilder=RequestBuilder(object :RxObservableListener<HttpResult<List<WeChatNews>>>(mView){
override fun onNext(result: HttpResult<List<WeChatNews>>) {
mView?.refreshUI(result.result)
}
})
requestBuilder
.setUrl(ApiUrl.URL_WETCHAT_FEATURED)
.setTransformClass(WeChatNews().javaClass)
.setHttpTypeAndReqType(RequestBuilder.HttpType.DEFAULT_GET,RequestBuilder.ReqType.NO_CACHE_LIST)
.setParam("page",page)
.setParam("type","video")
.setParam("count",num)
rxManager.addObserver(DataManager.DataForHttp.httpRequest(requestBuilder))
複製程式碼
(4)DataForSharePreferences
1.插入基本資料
DataManager.DataForSharePreferences.saveObject("user","這是一條測試的內容")
ToastUtils.showToast(activity,"儲存成功")
複製程式碼
2.查詢基本型別資料
val con=DataManager.DataForSharePreferences.getObject("user","")
ToastUtils.showToast(activity,con!!)
複製程式碼
六.Base的使用
1.為了方便Activity/Fragment設定頂部選單欄,繼承IBaseActivity/IBaseFragment即可顯示一個簡單的頂部選單,IBaseFragment的頂部選單預設隱藏,下面以IBaseActivity的頂部選單作為例子
屬性 | 作用 |
---|---|
isShowSystemActionBar | 重寫該方法設定實現顯示系統ActionBar |
isShowCustomActionBar | 重寫該方法設定顯示自定義Bar |
setCustomActionBar | 重寫該方法設定自定義Bar |
- 如果使用預設自定義Bar可通過DefaultDefineActionBarConfig進行相關設定
屬性 | 作用 |
---|---|
hideBackBtn | 隱藏返回按鈕 |
setBarBackgroundColor | 設定Bar的背景顏色 |
setBarHeight | 設定Bar的高度 |
setTitleColor | 設定標題顏色 |
setTitle | 設定標題 |
setBackClick | 設定返回按鈕監聽 |
-
程式碼使用
defineActionBarConfig .setTitleSize(20f) .setBarHeight(DisplayUtils.dip2px(this,60f)) .setBarBackgroundColor(this,R.color.driver_font) .setTitle(getString(R.string.tab_Indicator_title))
2.StateView(資料載入頁面)
屬性 | 作用 |
---|---|
STATE_NO_DATA | 不顯示載入框狀態碼 |
STATE_LOADING | 載入資料顯示狀態碼 |
STATE_EMPTY | 沒有資料顯示狀態碼 |
STATE_DISCONNECT | 沒有網路狀態碼 |
setOnDisConnectViewListener | 點選沒有網路圖示回撥 |
setOnEmptyViewListener | 點選沒有沒有資料圖示回撥 |
showViewByState | 設定顯示狀態 |
getmEmptyView | 獲取無資料狀態View |
佈局可設定引數 | |
loadingViewAnimation | 設定載入的drawable動畫 |
loadingText | 載入時的文字 |
emptyImage | 空佈局顯示的圖片 |
emptyText | 空佈局文字 |
emptyViewRes | 設定自定義空佈局 |
disConnectImage | 設定斷網顯示的圖片 |
disConnectText | 設定斷網顯示的文字 |
tipTextSize | 文字字型大小 |
tipTextColor | 文字字型顏色 |
(1)定義一個通用佈局
<com.youngmanster.collection_kotlin.base.stateview.StateView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:id="@+id/state_view">
</com.youngmanster.collection_kotlin.base.stateview.StateView >
複製程式碼
(2)新增到Ui頁面的layout中
<include layout="@layout/layout_state"/>
複製程式碼
注意:上面的語句新增的layout最外層最好是LinearLayout以及設定為android:orientation="vertical"
(3)通過以下語句進行狀態切換
stateView.showViewByState(StateView.STATE_LOADING)
stateView.showViewByState(StateView.STATE_EMPTY)
stateView.showViewByState(StateView.STATE_NO_DATA)
stateView.showViewByState(StateView.STATE_DISCONNECT)
複製程式碼
3.三步實現Permission(許可權)設定
(1)設定好要請求的許可權
// 專案的必須許可權,沒有這些許可權會影響專案的正常執行
private val PERMISSIONS = arrayOf(
Manifest.permission.READ_SMS,
Manifest.permission.RECEIVE_WAP_PUSH,
Manifest.permission.READ_CONTACTS
)
複製程式碼
(2)許可權通過PermissionManager管理
permissionManager = PermissionManager
.with(this)
.setNecessaryPermissions(PERMISSIONS)
permissionManager?.requestPermissions()
複製程式碼
(3)頁面重寫onRequestPermissionsResult
//重寫
override fun onRequestPermissionsResult(requestCode: Int, @NonNull permissions: Array<String>, @NonNull grantResults: IntArray) {
if (requestCode == PermissionManager.PERMISSION_REQUEST_CODE) {//PERMISSION_REQUEST_CODE為請求許可權的請求值
//有必須許可權選擇了禁止
if (permissionManager?.shouldShowRequestPermissionsCode == PermissionManager.EXIST_NECESSARY_PERMISSIONS_PROHIBTED) {
ToastUtils.showToast(this, "可以在這裡設定重新跳出許可權請求提示框")
} //有必須許可權選擇了禁止不提醒
else if (permissionManager?.shouldShowRequestPermissionsCode == PermissionManager.EXIST_NECESSARY_PERMISSIONS_PROHIBTED_NOT_REMIND) {
ToastUtils.showToast(this, "可以在這裡彈出提示框提示去應用設定頁開啟許可權")
permissionManager?.startAppSettings()
}
}
}
複製程式碼
注意:如果有需求先判斷是否所有許可權都已經允許之後再進入主頁面可以通過permissionManager.isLackPermission()進行判斷,如果返回true則進行許可權請求,如果返回false則進入主頁面。
- 多個許可權請求如果其中某一個被禁止提醒,會先把沒有禁止提醒的許可權處理完之後再進行處理。
- 如果是必要許可權被禁止而沒有選擇禁止提醒退出之後下次會重新請求許可權。
- 如果必要許可權被禁止和選擇了禁止提醒重新進入頁面在onRequestPermissionsResult會重新回撥方法。
- 使用者可以根據onRequestPermissionsResult()方法中返回來的標誌PermissionManager.EXIST_NECESSARY_PERMISSIONS_PROHIBTED和PermissionManager.EXIST_NECESSARY_PERMISSIONS_PROHIBTED_NOT_REMIND做出對應的顯示和操作(例如彈框提示跳轉到設定頁面或者toat提示)。
4.提供幾種比較常用的Dialog彈框
(1)提供的常用的CommonDialog
屬性 | 作用 |
---|---|
DIALOG_TEXT_TWO_BUTTON_DEFAULT | 預設彈出按鈕提示 |
DIALOG_TEXT_TWO_BUTTON_CUSTOMIZE | 自定義彈出按鈕提示 |
DIALOG_LOADING_PROGRASSBAR | 預設載入彈框 |
DIALOG_CHOICE_ITEM | 沒有資料顯示狀態碼 |
根據不同的建構函式設定不同的引數
(2)自定義Dialog樣式
- BaseDialog
屬性 | 作用 |
---|---|
setContentView | 設定彈框佈局樣式 |
show | 顯示彈框 |
isShowing | 判斷彈框是否顯示 |
dismiss | 彈框銷燬 |
setCancelable | 點選返回鍵和外部是否可以取消 |
setOnBackPressDialogCancel | 設定為false時,點選彈框外部不可消失,點選返回按鈕可以消失 |
setDialogInterval | 設定彈框和螢幕兩邊的間距 |
setDialogHeight | 設定彈框高度 |
- 繼承BaseDialog,通過setContentView(R.layout.dialog_list)設定彈窗佈局。
- 在提供的onViewCreated方法中進行相應的邏輯設定
5.自定義PopupWindow彈框
- BasePopupWindow
屬性 | 作用 |
---|---|
BasePopupWindow(Context context) | 呼叫該建構函式預設彈出框鋪滿全屏 |
BasePopupWindow(Context context, int w, int h) | 自定義彈出框高寬 |
showPopup | 在螢幕中央顯示彈框 |
showPopupAsDropDown | 在指定控制元件底部顯示彈框 |
showPopup | 在螢幕中央顯示彈框 |
showPopupAsDropDown | 在指定控制元件底部顯示彈框 |
setShowMaskView | 設定是否顯示遮層 |
dismiss | 銷燬彈出框 |
getPopupLayoutRes | 自定義彈出框的佈局檔案 |
getPopupAnimationStyleRes | 自定義彈出框的動畫檔案,不設定動畫返回0 |
- 繼承BasePopupWindow。
- 通過getPopupLayoutRes(R.layout.xxx)設定彈窗佈局。
- 通過getPopupAnimationStyleRes(R.style.xxx)設定彈窗動畫,不需要動畫可以設定為0。
- 如果需要顯示遮層,在建構函式通過setShowMaskView(true)設定。
七、CustomView的使用
1.CommonTabLayout的使用
屬性 | 作用 |
---|---|
tab_tabIndicatorWidth | 設定下滑線的長度 |
tab_tabIndicatorHeight | 設定下滑線的高度 |
tab_tabIndicatorColor | 下滑線顏色 |
tab_indicator_marginLeft | 設定下滑線外邊距 |
tab_indicator_marginRight | 設定下滑線外邊距 |
tab_indicator_marginTop | 設定下滑線外邊距 |
tab_indicator_marginBottom | 設定下滑線外邊距 |
tab_tabTextColor | 沒選中字型顏色 |
tab_tabTextSize | 字型大小 |
tab_tabSelectedTextColor | 選中字型顏色 |
tab_padding | 下滑線內邊距,block樣式時可以通過該屬性設定距離 |
tab_tabBackground | Tab 的背景顏色 |
tab_indicator_corner | 下滑線的圓角大小 |
tab_indicator_gravity(bottom、top | 設定下滑線顯示的位置,只針對line和triangle |
tab_tabMode(scrollable、fixed) | Tab的顯示模式 |
tab_indicator_style(line、triangle、block) | 下滑線的樣式 |
具體可參照例子使用。
2.OutSideFrameTabLayout的使用
屬性 | 作用 |
---|---|
tab_tabIndicatorColor | 設定Tab顏色 |
tab_indicator_corner | 圓角大小 |
tab_indicator_marginLeft | 下滑線外邊距 |
tab_indicator_marginRight | 下滑線外邊距 |
tab_indicator_marginTop | 下滑線外邊距 |
tab_indicator_marginBottom | 下滑線外邊距 |
tab_tabTextColor | 沒選中字型顏色 |
tab_tabSelectedTextColor | 選中字型顏色 |
tab_tabTextSize | 字型大小 |
tab_tabSelectedTextColor | 選中字型顏色 |
tab_padding | 內邊距 |
tab_bar_color | bar的背景顏色 |
tab_bar_stroke_color | 外框的顏色 |
tab_bar_stroke_width | 外框的大小 |
tab_width | bar的長度 |
具體可參照例子使用。
3.AutoLineLayout的使用
-
在外層佈局使用AutoLineLayout
<com.youngmanster.collection_kotlin.base.customview.wraplayout.AutoLineLayout android:layout_width="match_parent" android:layout_height="wrap_content"> </com.youngmanster.collection_kotlin.base.customview.wraplayout.AutoLineLayout> 複製程式碼
4.TagView的使用
TagViewConfigBuilder
屬性 | 作用 |
---|---|
setTitles | 設定TagItem內容 |
setTextSize | 設定TagItem字型大小 |
setTextColor | 設定TagItem字型顏色 |
setTextSelectColor | 設定TagItem選擇字型顏色 |
setPaddingLeftAndRight | 設定TagIttem左右內邊距 |
setPaddingTopAndBottom | 設定TagIttem上下內邊距 |
setMarginAndTopBottom | 設定TagItem上下外邊距 |
setMarginLeftAndRight | 設定TagItem左右外邊距 |
setackgroudRes | 設定background Drawable |
setTagViewAlign | 設定整體TagItem的Align(LEFT,RIGHT,CENTER) |
1.佈局
<com.youngmanster.collection_kotlin.base.customview.tagview.TagView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/tagView" />
複製程式碼
2.程式碼設定
tagView.create(builder,object :TagView.TagViewPressListener{
override fun onPress(view: View, title: String, position: Int) {
ToastUtils.showToast(this@TagViewActivity,title)
}
})
複製程式碼
八、工具類的使用
1.Density(適配不同手機畫素)
- 在Applicaton的onCreate中設定 Density.setDensity(this, 375f)
- 375f代表設計稿的寬度,以dp為單位,後面需要以f(浮點型)
2.DisplayUtils
屬性 | 作用 |
---|---|
px2dip | px值轉換為dip或dp值,保證尺寸大小不變(有精度損失) |
px2dipByFloat | px值轉換為dip或dp值,保證尺寸大小不變(無精度損失 |
dip2px | dip或dp值轉換為px值,保證尺寸大小不變(有精度損失),類似Context.getDimensionPixelSize方法(四捨五入 |
dip2pxByFloat | dip或dp值轉換為px值,保證尺寸大小不變(無精度損失),類似Context.getDimension方法 |
px2sp | px值轉換為sp值,保證文字大小不變 |
sp2px | sp值轉換為px值,保證文字大小不變 |
getScreenWidthPixels | 螢幕寬度 |
getScreenHeightPixels | 螢幕高度 |
getDisplayInfo | 獲取裝置資訊 |
setStatusBarBlackFontBgColor | 設定黑色字型狀態的背景顏色 |
setStatusBarColor | 設定狀態列背景顏色 |
setStatusBarFullTranslucent | 設定狀態列透明 |
getStatusBarHeight | 獲取狀態列高度 |
getActionBarHeight | 獲取ActionBar高度 |
3.ColorUtils
屬性 | 作用 |
---|---|
createColorStateList | 獲取ColorStateList |
4.FileUtils
屬性 | 作用 |
---|---|
WriterTxtFile | 寫檔案,其中append可設定是否新增在原內容的後邊 |
ReadTxtFile | 讀取文字檔案中的內容,strFilePath代表檔案詳細路徑 |
isCacheDataFailure | 判斷快取是否失效 |
checkFileExists | 檢查檔案是否存在 |
checkSaveLocationExists | 檢查是否安裝SD卡 |
deleteDirectory | 刪除目錄(包括:目錄裡的所有檔案) |
deleteFile | 刪除檔案 |
getFileOrFilesSize | 獲取檔案指定檔案的指定單位的大小,其中sizeType 獲取大小的型別1為B、2為KB、3為MB、4為GB |
getFileSize | 獲取指定檔案大小 |
5.GetPermissionsUtils
屬性 | 作用 |
---|---|
getAllPermissons | 獲取應用用到的所有許可權 |
6.GlideUtils
屬性 | 作用 |
---|---|
loadImg | 載入圖片 |
loadImgBlur | Glide實現高斯模糊 |
loadImgBlur | Glide實現高斯模糊,可設定模糊的程度 |