Skip to content

Generate AsyncTask

xcesco edited this page May 2, 2018 · 1 revision

Async Tasks allows working with jobs that can not be executed on UI thread. Usually, Async Tasks are created to be used in activity or fragment classes. Working with SQLite database, you need to specialize async tasks to persist data on other thread than Main thread.

Kripton annotation processor can generate for us a specialized kind of Async Task that simplify operation with data-source. The Async Task generation is controlled by @BindDataSource#asyncTask attribute.

The generated async task class unlike standard Async Task, can be reused many times.

@BindDataSource(daoSet= { PersonDAO.class }, fileName = "person.db", asyncTask=true)
public interface PersonDataSource {

}

The generated async task will be named BindPersonAsyncTask: data source name PersonDataSource will be prefixed by Bind and DataSource suffix will be replaced with AsyncTask.

public abstract class BindPersonAsyncTask<I, U, R> {
  /**
   * Allows to specify how async task interacts with data source.
   *
   */
  protected BindAsyncTaskType mode;

  /**
   * Async task wrapped by this class
   *
   */
  protected AsyncTask<I, U, R> asyncTask;

  /**
   * <p>
   * With this constructor, a read only database connection will be used
   * </p>
   */
  public BindPersonAsyncTask() {
    this(BindAsyncTaskType.READ);
  }

  /**
   * <p>
   * With this constructor it is possible to specify which type of database use in async task
   * </p>
   *
   * @param mode allows to specify if and how open a data source connection
   */
  public BindPersonAsyncTask(BindAsyncTaskType mode) {
    this.mode = mode;}

  /**
   * Use this method for operations on UI-thread before start execution
   */
  public void onPreExecute() {
  }

  /**
   * Method used to encapsulate operations on datasource
   *
   * @param dataSource
   * 	use it to retrieve DAO
   * @return
   * 	result of operation (list, bean, etc) and execute transactions.
   */
  public abstract R onExecute(BindPersonDataSource dataSource) throws Throwable;

  /**
   * Use this method for operations on UI-thread after execution
   */
  public abstract void onFinish(R result);

  /**
   * Override this method to KRIPTON_DEBUG operation progress on UI-Thread
   */
  public void onProgressUpdate(U... update) {
  }

  /**
   * This method is invoked when <code>onExecute</code> method generate an exception.
   * @param exception exception generated
   */
  public void onError(Throwable exception) {
    Logger.error(exception.getMessage());
    exception.printStackTrace();
  }

  /**
   * Method to start operations.
   *
   * @param executor used executor
   * @param data input
   */
  public void execute(@SuppressWarnings("unchecked") I... params) {
    executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);
  }

  /**
   * Method to start operations.
   *
   * @param executor used executor
   * @param data input
   */
  public void executeOnExecutor(Executor executor, @SuppressWarnings("unchecked") I... params) {
    asyncTask=new AsyncTask<I, U, R>() {
      @Override
      public void onPreExecute() {
        BindPersonAsyncTask.this.onPreExecute();
      }

      @Override
      public R doInBackground(@SuppressWarnings("unchecked") I... params) {
        BindPersonDataSource dataSource=BindPersonDataSource.instance();
        R result=null;
        if (mode==BindAsyncTaskType.READ) dataSource.openReadOnlyDatabase(); else if (mode==BindAsyncTaskType.READ_WRITE) dataSource.openWritableDatabase();
        try {
          result=onExecute(dataSource);
        } catch(Throwable e) {
          onError(e);
        } finally {
          if (dataSource.isOpen()) {
            dataSource.close();
          }
        }
        return result;
      }

      @Override
      public void onProgressUpdate(@SuppressWarnings("unchecked") U... values) {
        BindPersonAsyncTask.this.onProgressUpdate(values);
      }

      @Override
      public void onPostExecute(R result) {
        BindPersonAsyncTask.this.onFinish(result);
      }
    };
    asyncTask.executeOnExecutor(executor, params);
  }

  /**
   * Simple implementation of async task. It uses read only database.
   *
   * @see BindPersonDaoFactory
   * @see BindPersonDataSource
   */
  public abstract static class Simple<R> extends BindPersonAsyncTask<Void, Void, R> {
    /**
     * Create an simple async task allowing user to decide which kind of operation can be done on datasource */
    public Simple(BindAsyncTaskType mode) {
      super(mode);
    }

    /**
     * Create an simple async task for data source read only operation */
    public Simple() {
      super(BindAsyncTaskType.READ);
    }
  }
}

BindPersonAsyncTask can be used as a normal Async Task. Moreover a BindPersonAsyncTask.Simple is generated to manage simpliest situation when you only need to do some operation on database and then store result on UI. An example of usage:

BindPersonAsyncTask.Simple<Person> asyncTask=new BindPersonAsyncTask.Simple<Person>() {
			
  @Override
  public void onFinish(Person result) {
    // executed on Main thread
  }
			
  @Override
  public Person onExecute(BindPersonDataSource dataSource) throws Throwable {
    // do some opearation on another thread
  }
};

Generated Async Task can be used with UNMANAGE connection, a READ only connection or a READ_WRITE connection. Usage type is piloted by a optional [BindAsyncTaskType](https://github.com/xcesco/kripton/blob/master/kripton-orm/src/main/java/com/abubusoft/kripton/android/BindAsyncTaskType.java) parameter passed to the class in the constructor.

Table of Contents

Query definition

Features

Relations

Multithread supports

Modularization

Annotations for data convertion

Annotations for SQLite ORM

Annotations for shared preferences

Clone this wiki locally