PreLoaderAndroid頁面啟動速度優(yōu)化利器
預(yù)加載:android頁面啟動速度優(yōu)化利器,在頁面打開之前就預(yù)加載數(shù)據(jù)
Activity打開之前就預(yù)加載數(shù)據(jù),在Activity的UI布局初始化完成后顯示預(yù)加載的數(shù)據(jù),大大縮短啟動時間。
在任意處開啟預(yù)加載任務(wù),并生成任務(wù)id,根據(jù)任務(wù)id可在任意處(一般是UI初始化完成后)開始對預(yù)加載的數(shù)據(jù)進行監(jiān)聽。
開始進行監(jiān)聽時,若預(yù)加載任務(wù)未完成,則等待任務(wù)加載完成后執(zhí)行監(jiān)聽對象的回調(diào)方法
開始進行監(jiān)聽時,若預(yù)加載任務(wù)已完成,則直接執(zhí)行監(jiān)聽對象的回調(diào)方法
持續(xù)優(yōu)化中,歡迎watch、star關(guān)注!
Demo
典型應(yīng)用
1. 在Application.onCreate中加載地址數(shù)據(jù),在需要用到地址的頁面中獲取預(yù)加載的數(shù)據(jù)
2. 在啟動頁中預(yù)加載app主頁所需的數(shù)據(jù),減少用戶等待時間
3. startActivity之前就開始預(yù)加載,UI初始化完成后顯示預(yù)加載的數(shù)據(jù)
4. 復(fù)雜頁面(UI初始化耗時較多的頁面)內(nèi)部在UI初始化開始之前預(yù)加載數(shù)據(jù),UI初始化完成后顯示預(yù)加載的數(shù)據(jù)
5. ListView/RecyclerView在上拉加載更多之前預(yù)加載下一頁的數(shù)據(jù)
功能列表
支持網(wǎng)絡(luò)數(shù)據(jù)、網(wǎng)絡(luò)圖片、本地圖片、數(shù)據(jù)庫查詢及文件I/O等各種耗時操作的預(yù)加載
支持跨Activity預(yù)加載
支持下拉刷新(DataLoader重新加載一遍,加載完成后,回調(diào)所有DataListener)
支持自定義線程池
支持一個加載任務(wù)(DataLoader)對應(yīng)多個監(jiān)聽器(DataListener)
支持為一個Activity配置多個預(yù)加載任務(wù)
支持后續(xù)添加/移除監(jiān)聽器(DataListener)
支持多個預(yù)加載任務(wù)分組管理
使用方法
1. 在build.gradle中添加依賴
dependencies {
compile 'com.billy.android:pre-loader:x.x.x'
}
2. 開啟預(yù)加載任務(wù)(如:在startActivity之前開啟)
int preLoaderId = PreLoader.preLoad(new Loader());
Intent intent = new Intent(this, PreLoadBeforeLaunchActivity.class);
intent.putExtra("preLoaderId", preLoaderId);
startActivity(intent);
//預(yù)加載任務(wù):模擬網(wǎng)絡(luò)接口請求獲取數(shù)據(jù)
class Loader implements DataLoader<String> {
@Override
public String loadData() {
//此方法在線程池中運行,無需再開子線程去加載數(shù)據(jù)
try {
Thread.sleep(600);
} catch (InterruptedException ignored) {
}
return "data from network server";
}
}
3. 在Activity(或Fragment)中UI初始化完成后開始監(jiān)聽預(yù)加載數(shù)據(jù)
PreLoader.listenData(preLoaderId, new Listener());
//數(shù)據(jù)加載完成后,會調(diào)用DataListener.onDataArrived(...)來處理加載后的數(shù)據(jù)
class Listener implements DataListener<String> {
@Override
public void onDataArrived(String data) {
//此方法在主線程中運行,無需使用Handler切換線程運行
Toast.makeText(activity, data, Toast.LENGTH_SHORT).show();
}
}
4. 刷新數(shù)據(jù),DataLoader會重新加載一遍數(shù)據(jù),加載完成后,所有的DataListener的回調(diào)方法會被執(zhí)行
PreLoader.refresh(preLoaderId);
5. 在使用完成后可以對預(yù)加載任務(wù)進行銷毀(如:在onDestroy中)
PreLoader.destroy(preLoaderId);
6. 用GroupedDataLoader和GroupedDataListener來開啟多個預(yù)加載任務(wù)(解決頁面中有多個預(yù)加載任務(wù)時id管理不方便的問題)
//用GroupedDataLoader開啟一組預(yù)加載任務(wù),共用同一個id
int preLoaderId = PreLoader.preLoad(new Loader1(), new Loader2());
Intent intent = new Intent(this, PreLoadGroupBeforeLaunchActivity.class);
intent.putExtra("preLoaderId", preLoaderId);
startActivity(intent);
class Loader1 implements GroupedDataLoader<String> {
@Override
public String loadData() {
TimeWatcher timeWatcher = TimeWatcher.obtainAndStart("GroupedDataLoader1 load data");
try {
Thread.sleep(600);
} catch (InterruptedException ignored) {
}
return timeWatcher.stopAndPrint();
}
@Override
public String keyInGroup() {
return "loader1";
}
}
class Loader2 implements GroupedDataLoader<String> {
@Override
public String loadData() {
TimeWatcher timeWatcher = TimeWatcher.obtainAndStart("GroupedDataLoader2 load data");
try {
Thread.sleep(400);
} catch (InterruptedException ignored) {
}
return timeWatcher.stopAndPrint();
}
@Override
public String keyInGroup() {
return "loader2";
}
}
//在UI初始化完成后開始用GroupedDataListener對數(shù)據(jù)進行監(jiān)聽
//GroupedDataListener 與 GroupedDataLoader 之間用key進行關(guān)聯(lián)
// 可以一次開啟多個監(jiān)聽
PreLoader.listenData(preLoaderId
, new DataHolder1()
, new DataHolder2()
);
//也可以分別監(jiān)聽
PreLoader.listenData(preLoaderId, new DataHolder1());
PreLoader.listenData(preLoaderId, new DataHolder2());
class DataHolder1 implements GroupedDataListener<String> {
@Override
public void onDataArrived(String data) {
String s = allTime.stopAndPrint();
logTextView.append(data + "\n" + s + "\n");
}
@Override
public String keyInGroup() {
return "loader1";
}
}
class DataHolder2 implements GroupedDataListener<String> {
@Override
public void onDataArrived(String data) {
String s = allTime.stopAndPrint();
logTextView.append(data + "\n" + s + "\n");
}
@Override
public String keyInGroup() {
return "loader2";
}
}
配合組件化開發(fā)框架( CC )使用效果更佳
CC框架自帶組件層級的AOP,在組件被調(diào)用打開Activity之前進行預(yù)加載,不需要在每個打開這個Activity的地方調(diào)用預(yù)加載。
組件定義打開Activity的功能:
public class ComponentA implements IComponent {
@Override
public String getName() {
return "demo.ComponentA";
}
@Override
public boolean onCall(CC cc) {
int preLoaderId = PreLoader.preLoad(new Loader());
Intent intent = new Intent(this, PreLoadBeforeLaunchActivity.class);
intent.putExtra("preLoaderId", preLoaderId);
startActivity(intent);
CC.sendCCResult(cc.getCallId(), CCResult.success());
return false;
}
}
調(diào)用打開PreLoadBeforeLaunchActivity的組件:
//不需要執(zhí)行預(yù)加載,加載數(shù)據(jù)的邏輯在頁面所屬的組件內(nèi)部完成
CC.obtainBuilder("demo.ComponentA").build().call();
