Skip to content
Pre-load data for android Activity/Fragment/View (android页面启动速度优化利器:在页面打开之前就预加载数据)
Branch: master
Clone or download
Latest commit 2b023c4 Aug 22, 2018
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.idea first commit Dec 31, 2017
app
gradle/wrapper
image first commit Dec 31, 2017
pre-loader
.gitignore first commit Dec 31, 2017
LICENSE
README-zh-CN.md update README for version:2.0.0 Jan 24, 2018
README.md update README for version:2.0.0 Jan 24, 2018
bintray.gradle first commit Dec 31, 2017
build.gradle
changelog.md
demo.apk
gradle.properties first commit Dec 31, 2017
gradlew first commit Dec 31, 2017
gradlew.bat
settings.gradle
store.keystore

README.md

PreLoader: Make your activity launch faster

Download

GitHub stars GitHub forks

changelog

中文文档

Pre-load data before Activity opens, and display data on UI after UI initialization. Speedup Activity launch

You can start a PreLoader everywhere and start to listen data which loaded by the PreLoader with preLoaderId

  • if DataLoader.loadData() is not completed, then DataListener.onDataArrived() will be called after the data load is completed

  • if DataLoader.loadData() is completed, then DataListener.onDataArrived() called immediately

Continuous optimization, welcome watch, star!

demo

demo download

Typically used for

  1. Pre-load data in Application.onCreate for HomePageActivity to reduce the user waiting time in HomePageActivity initialization

  2. Pre-load data before context.startActivity(), and display data after activity UI are initialized

  3. Pre-load data for complex UI Activity (UI initialization cost too much time)

  4. Pre-load data for next page of ListView/RecyclerView before pull to load more

Features

  • support network data, network images, local images, database queries, and file I/O

  • support for cross-activity pre-loading

  • support pull-down refresh (DataLoader reloads once, after loading completes, callback for all DataListener)

  • supports custom thread-pool

  • support one loader (DataLoader) for multiple listeners (DataListener)

  • support multiple preload tasks for an Activity

  • support for add/remove listener dynamically

image

Usage

  1. add dependencies in build.gradle
dependencies {
    compile 'com.billy.android:pre-loader:x.x.x'
}
  1. start a pre-load
int preLoaderId = PreLoader.preLoad(new Loader());
Intent intent = new Intent(this, PreLoadBeforeLaunchActivity.class);
intent.putExtra("preLoaderId", preLoaderId);
startActivity(intent);

//DataLoader, mock as load data from network
class Loader implements DataLoader<String> {
    @Override
    public String loadData() {
        //this method runs in thread pool
        // load data in this method synchronously
        try {
            Thread.sleep(600);
        } catch (InterruptedException ignored) {
        }
        return "data from network server";
    }
}
  1. Listen data after UI initialization in Activity/Fragment/View
PreLoader.listenData(preLoaderId, new Listener());

//after data load completed,DataListener.onDataArrived(...) will be called to process data
class Listener implements DataListener<String> {
    @Override
    public void onDataArrived(String data) {
        // this method runs on main thread, Handler is not required
        Toast.makeText(activity, data, Toast.LENGTH_SHORT).show();
    }
}
  1. Refresh data: DataLoader.loadData() will be called, and DataListener.onDataArrived() will be called for all listeners
PreLoader.refresh(preLoaderId);
  1. Destroy the PreLoader object if you do not need it(eg. Activity is destroyed)
PreLoader.destroy(preLoaderId);
  1. start a group of pre-load task with GroupedDataLoader and GroupedDataListener
//start pre-load task with a group of GroupedDataLoader(s)
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";
    }
}

//listen data in Activity after UI initialization with GroupedDataListener(s) for each GroupedDataLoader(s)
//GroupedDataListener matched with GroupedDataLoader by key
PreLoader.listenData(preLoaderId
        , new DataHolder1()
        , 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";
    }
}

Better to use with the componentized architecture framework (CC)

CC framework comes with AOP at the component level: when component is calling for start an activity, you can start a pre-load for it. So, it is not need to do pre-load work in every place where you want to start the Activity.

  1. define a component for open the 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;
    }
}

call that component by CC to open activity

// pre-load is needless here, the logistic of component are all inside that component itself
CC.obtainBuilder("demo.ComponentA").build().call();
You can’t perform that action at this time.