PreLoader

Project Url: luckybilly/PreLoader
Introduction: Pre-load data for android Activity/Fragment/View (android 页面启动速度优化利器:在页面打开之前进行预加载)
More: Author   ReportBugs   
Tags:
性能优化-android-网络请求-

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'
    }
    
  2. start a pre-load ```java 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 { @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"; } }


3. Listen data after UI initialization in Activity/Fragment/View
```java

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);
    
  2. Destroy the PreLoader object if you do not need it(eg. Activity is destroyed)

    PreLoader.destroy(preLoaderId);
    
  3. start a group of pre-load task with GroupedDataLoader and GroupedDataListener ```java //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 { @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 { @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 { @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 { @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](https://github.com/luckybilly/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
```java
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();
Support Me
Apps
About Me
Google+: Trinea trinea
GitHub: Trinea