I want to execute below methods in order. That means, if A methods ends, B starts. If B ends C starts and so forth.
public void InitializeAPI {
public static void init_A(Context mContext) {
Realm.init(mContext);
Realm realm = Realm.getDefaultInstance();
realm.executeTransactionAsync(new Realm.Transaction() {
#Override
public void execute(Realm realm) {
// Some working is here.
}
}, new Realm.Transaction.OnSuccess() {
// Some proceesing lines are here.
}, new Realm.Transaction.OnError() {
Log.d("AsyncTransaction", "ERROR");
});
// And there are lots of other TransactionAsync() line in this methods.
}
public static void init_B(Context mContext) {...}
public static void init_C(Context mContext) {...}
// and So many initialize methods.
}
As you can see, when I execute init_A(Context), Async Transaction will be in background.
But the problem is init_B needs to be executed after init_A ending. init_C also. How can I design this matter??
Of course, I know that there is Realm.Transaction.OnSuccess() But, If I write init_B in Realm.Transaction.OnSuccess() at init_A, I think that codes won't be neat or good to Maintenance.
Why don't you use something like this:
realm.beginTransaction();
//... add or update objects here ...
realm.commitTransaction();
instead of a async call.
It will ensure that code will work synchronously.
Hope it helps..!
you could send a message though handler in the OnSuccess to trigger the init_B. But that doesn't look much better. So if you want to do the initialization without blocking the UI, creating your own thread might a good choice.
public void InitializeAPI {
public static void init_A(Context mContext) {
Realm.init(mContext);
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
// Write data
realm.commitTransaction();
realm.close();
}
public static void init_B(Context mContext) {...}
public static void init_C(Context mContext) {...}
// and So many initialize methods.
public static void init() {
init_A();
init_B();
init_C();
//...
}
}
Thread thread = new Thread(new Runnable() {
#Override
public void run() {
InitializeAPI.init();
// Notify the main thread that initialization is done.
handler.post(initialziedRunnable);
}
});
thread.start();
Related
I'm fairly new to RxJava and I have a basic understanding as to how to wrap a callback into an Observable but what I'm having difficulty with is doing so when the callback/listener is pre-instanced. Every example that I have found only shows instancing the callback directly into the Observable being created.
Some example code of what I'm talking about. I'm working with an Api that's works like this:
public class Api {
private ApiCallback callback;
void initialize(ApiCallback callback){
this.callback = callback;
}
void doAction1(){
this.callback.onAction1Complete();
}
}
interface ApiCallback {
void onInitialized();
void onAction1Complete();
}
With the real api I am working with I have no control over how it works so I must work with it in this state. In terms of trying to work with this Api using observables here is the struggle I am having. I have a member variable that holds the Api object:
private Api mApi = new Api();
Now in order to initialize this I have one of two options it seems.
Option 1:
Completable startApi() {
return Completable.create(new CompletableOnSubscribe() {
#Override
public void subscribe(final CompletableEmitter emitter) throws Exception {
mApi.initialize(new ApiCallback() {
#Override
public void onInitialized() {
emitter.onComplete();
}
#Override
public void onAction1Complete() {
}
});
}
});
}
Option 2:
private ApiCallback premadeCallback = new ApiCallback() {
#Override
public void onInitialized() {
}
#Override
public void onAction1Complete() {
}
};
Completable startApi() {
return Completable.create(new CompletableOnSubscribe() {
#Override
public void subscribe(final CompletableEmitter emitter) throws Exception {
mApi.initialize(premadeCallback);
}
});
}
Now the issue I have is that Option 2 makes more sense to me when I need to know when the other methods in the callback are called from Api calls. With my understanding of RxJava however I don't understand how I can reach these method calls with an Api that works like this.
For example:
Completable doAction1() {
return Completable.create(new CompletableOnSubscribe() {
#Override
public void subscribe(final CompletableEmitter emitter) throws Exception {
// Api is already initialized with callback
// How do I reach the callback from here?
}
});
}
The only what that I can currently think of as to how to achieve this would be to create a member variable as an emitter (or a dictionary of emitters) and then call its appropriate method in the api callback when needed. My concerns with this are A. I'm unsure if RxJava can work this way B. This sounds like a terrible idea.
As far as I know, there is two way to insert element to database.
In first one, we can insert like this
realm.beginTransaction();
UsersTable usersTable = realm.createObject(UsersTable.class);
usersTable.setName(name);
usersTable.setSurname(surname);
usersTable.setAge(age);
usersTable.setSalary(salary);
realm.commitTransaction();
In second one, we have different kind of method to insert
realm.executeTransactionAsync(new Realm.Transaction () {
public void execute(Realm realm) {
//......
}
}, new Realm.Transaction.onSuccess() {
public void onSuccess(Realm realm) { }
}, new Realm.Transaction.onError() {
public void onSuccess(Realm realm) { }
}
What is the difference between them? It seems like the bottom one gives option to indicate something on both success and error.
realm.beginTransaction();
...
realm.commitTransaction();
This is synchronous transaction with no error handling (catch(Throwable e) { realm.cancelTransaction();). It is executed on the thread you are currently on.
realm.executeTransactionAsync(new Realm.Transaction () {
public void execute(Realm realm) {
//......
}
}, new Realm.Transaction.onSuccess() {
public void onSuccess(Realm realm) { }
}, new Realm.Transaction.onError() {
public void onSuccess(Realm realm) { }
}
This is asynchronous transaction. It can only be initiated from a Looper thread. It will run the transaction on Realm's background thread-pool.
The callbacks will be called only after Realm has updated the UI thread Realm.
I have AsyncTask class with methods like this(class: ApiConnector):
#Override
protected String doInBackground(Void... voids)
{
return getToken(); //<-- do many the most important things and return String
}
and
#Override
protected void onPostExecute(String result)
{
super.onPostExecute(result);
}
and then in my Activity:
new ApiConnector()
{
#Override
public void onPostExecute(String result)
{
Log.d("here: ", result);
}
}.execute();
It work's fine when I execute this one time, but i have to do this in endless loop to take always fresh token like fresh apples in my market. I tried something like that:
while (true)
{
new ApiConnector()
{
#Override
public void onPostExecute(String result)
{
Log.d("here!", result);
}
}.execute();
Thread.sleep(1000);
}
and many many stupid things, but i can't find working way. All thread bussiness is tricky for me. Give me some kick and I manage this for sure.
You don't want to do this. All AsyncTasks run on one thread. If you infinitely loop inside an AsyncTask, you'll starve all other tasks. If you have each task start a new task, then you'll still risk major starvation issues.
If you want to do this (and I'm not sure you really do, but lets ignore that), the correct way is to use a Thread. A Thread can just have a giant while(true) loop and a sleep statement at the end.
Like hrskrs commented I would prefer using a Handler to execute something repeatedly. The main advantage is that postDelayed makes the run() method execute in the main application thread - so you can access and change UI components.
Here's an example:
public class MyTest implements Runnable {
private final static int INTERVAL = 5000;
private Handler mHandler;
private MyTest() {
mHandler = new Handler();
}
public void start() {
run();
}
public void stop() {
mHandler.removeCallbacks(this);
}
#Override
public void run() {
// put here the logic that you want to be executed
mHandler.postDelayed(this, INTERVAL);
}
}
In the last days I have found myself using this approach for asynchronously performing some long operation (several seconds), and then return some value via a callback that must execute on the caller thread, which is typically but not necessarily the UI thread.
public abstract class DoSomethingCallback
{
public abstract void done(Object result);
}
public void doSomething(final Object param, final DoSomethingCallback doSomethingCallback)
{
// Instantiate a handler for the calling thread
final Handler handler = new Handler();
// Start running the long operation in another thread
new Thread(new Runnable() {
#Override
public void run() {
// Do a long operation using "param" as input...
Object result = longOperation(param);
// Return result via a callback, which will run in the caller thread
handler.post(new Runnable() {
#Override
public void run() {
doSomethingCallback.done(clearBytes);
}
});
}
}).start();
}
This seems to work pretty well and is very simple to use. However, I somehow suspect it might have some problems I'm not aware of. So the question is, what are the potential issues of this approach? What are better alternatives than manually creating and running a thread? I'm seeking for simplicity and robustness.
The only problem is that such approach breaks encapsulation: the second thread not only computes the result, but also dictates what the caller thread should do with it. So I'd better refactor your code as follows:
public abstract class DoSomethingCallback {
final Handler handler = new Handler();
public void post(final Object result) {
handler.post(new Runnable() {
#Override
public void run() {
doSomethingCallback.done(result);
}
});
}
public abstract void done(Object result);
}
public void doSomething(final Object param, final DoSomethingCallback doSomethingCallback) {
// Instantiate a handler for the calling thread
final DoSomethingCallback handler = new DoSomethingCallback () {
void done(Object result) {
...
}
};
// Start running the long operation in another thread
new Thread(new Runnable() {
#Override
public void run() {
// Do a long operation using "param" as input...
Object result = longOperation(param);
// Return result via a callback, which will run in the caller thread
handler.post(result);
});
}
}).start();
}
Ok, there isn't synchronous call in GWT.
But if i have something like this:
class XXX {
Config c=new Config();
c.doSomething();
}
and the class Config
public class Config {
private static HashMap<String,String> map;
public Config(){
final ServerProxyAsync serverProxy= GWT.create(ServerProxy.class);
serverProxy.getParameters(new AsyncCallback<HashMap<String,String>>() {
#Override
public void onFailure(Throwable caught) {
System.out.println("getParameters: FAILED!");
map=null;
}
#Override
public void onSuccess(HashMap<String, String> result) {
System.out.println("getParameters: OK!");
map=result;
// RETURN NOW!!!!
}
});
}
if the asynchronous call doesn't terminate I can't do doSomething(), because sometime the method is invoked before the map is initialized.
Is there a way?
How about doSomething() in onSuccess() ?
You can't use synchronous call in GWT.Even though you made it somehowits not a good practise
When you need this you have to do the stuff in the onSuccess(); of your RPC call .
So, the best idea is to simply use the asynchronous method and continue execution via the callbacks provided.You will end up with a much better user experience, and a more professional appearing
application.
Just extends your Config class to take a Runnable or a Callback. Something like this:
public class Config {
private static HashMap<String,String> map;
private final Runnable callback;
public Config(Runnable callback){
this.run = run;
final ServerProxyAsync serverProxy= GWT.create(ServerProxy.class);
serverProxy.getParameters(new AsyncCallback<HashMap<String,String>>() {
#Override
public void onFailure(Throwable caught) {
System.out.println("getParameters: FAILED!");
map=null;
}
#Override
public void onSuccess(HashMap<String, String> result) {
System.out.println("getParameters: OK!");
map=result;
callback.run();
}
});
}
}
Then you can use it like this:
class XXX {
final Runnable callback = new Runnable() {
#Override
public void run() {
dosomething1();
}
};
Config c=new Config(callback);
}