Android calling AsyncTask().get() without execute()? - android-asynctask

I'm having issues trying to understand how AsyncTask().get() actually works. I know it's a synchronous execution, However: I don't know how execute() and get() are connected.
I have this sample code from Google's docs:
// Async Task Class
class DownloadMusicfromInternet extends AsyncTask<String, String, String> {
// Show Progress bar before downloading Music
#Override
protected void onPreExecute() {
super.onPreExecute();
Log.d("Task: ", "onPreExecute()");
}
// Download Music File from Internet
#Override
protected String doInBackground(String... f_url) {
for (int i = 0; i < 100; i++){
try {
Thread.sleep(100);
Log.d("Task: ", String.valueOf(i));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return null;
}
// While Downloading Music File
protected void onProgressUpdate(String... progress) {
// Set progress percentage
Log.d("Task: ", "onProgressUpdate()");
}
// Once Music File is downloaded
#Override
protected void onPostExecute(String file_url) {
Log.d("Task: ", "onPostExecute()");
}
}
Now, from a button.onClick() I call this in 3 ways:
new DownloadMusicfromInternet().execute("");//works as expected, the "normal" way
//works the normal way, but it's synchronous
try {
new DownloadMusicfromInternet().execute("").get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
//does not work
try {
new DownloadMusicfromInternet().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
I'm confused as to how exactly execute() triggers doInBackground() and then immediately returns if get() is called, while get() has no effect on doInBackground() whatsoever.

execute() schedules the internal FutureTask (usually on a internal Executor) and returns immediately.
get() just calls FutureTask.get() on this internal future, i.e. it waits (if necessary) for the result.
So calling get() without calling execute() first waits indefinitely, as the result will never be available.
As you mentioned, when used the normal way, get() is not needed at all, as the result is handled in onPostExecute(). I didn't even know it existed before I tried to understand your question

Related

finally block - variable cannot be resolved

Java 8
import java.util.zip.GZIPOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
private void createFile(final String json) throws IOException {
final String fileName = getConfigFileName(this.getSomePath());
GZIPOutputStream out = null;
try {
out = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"));
out.write(json.getBytes());
} catch (IOException e) {
throw e;
} finally {
try {
if (out != null) {
out.finish();
out.close();
}
} catch (IOException e) {
LOGGER.error("createFile: IOException while closing resources", e);
}
}
}
Nice. This work fine.
Now I want to use try-with-resource
private void createFile(final String json) throws IOException {
final String fileName = getConfigFileName(this.getSomeFile());
try (GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"))) {
out.write(json.getBytes());
} catch (IOException e) {
throw e;
} finally {
try {
if (out != null) {
out.finish();
}
} catch (IOException e) {
LOGGER.error("createFile: IOException while closing resources", e);
}
}
}
But now I get error in this line:
if (out != null) {
Error is:
out cannot be resolved
I know this error is rise because variable out is on finally section.
But how I can use try-with-resources and execute method out.finish ?
From a technical perspective - a variable declared in the try argument isn't available in the finally clause, as you've seen. The good news here is that from a function perspective - finish() shouldn't be in the finally block anyway. finish is part of the positive (a.k.a "happy") flow, and should only be called when you're done writing to the stream. In other words, if the write operation failed and an exception was thrown, you shouldn't call finish anyway.
To make a long story short - move the finish call inside the try block:
Side note: Since your method throws an IOException, there's no reason to catch the exception and rethrow it. You can clean up the code by allowing it to be thrown from the method call directly:
private void createFile(final String json) throws IOException {
final String fileName = getConfigFileName(this.getSomeFile());
try (GZIPOutputStream out = new GZIPOutputStream(new FileOutputStream(fileName + ".gz"))) {
out.write(json.getBytes());
out.finish();
}
}

The info about new Tango()

I have downloaded the demo "java_quick_start_example".
1. I run the app directly, but it is failed. The log is described as
TangoErrorType TangoService_initialize (JNIEnv*, jobject): Done initializing, error code = -1
2. I modify the code as below
mTango = new Tango(this, new Runnable() {
#Override
public void run() {
}
});
It is failed, too. The log is described as "Error - TangoService_connectOnPoseAvailable: -1"
some example pull from Tango Example :
mTango = new Tango(MotionTrackingActivity.this, new Runnable() {
// Pass in a Runnable to be called from UI thread when Tango is ready,
// this Runnable will be running on a new thread.
// When Tango is ready, we can call Tango functions safely here only
// when there is no UI thread changes involved.
#Override
public void run() {
mConfig = setupTangoConfig(mTango);
try {
setTangoListeners();
} catch (TangoErrorException e) {
Log.e(TAG, getString(R.string.exception_tango_error), e);
} catch (SecurityException e) {
Log.e(TAG, getString(R.string.permission_motion_tracking), e);
}
try {
mTango.connect(mConfig);
} catch (TangoOutOfDateException e) {
Log.e(TAG, getString(R.string.exception_out_of_date), e);
} catch (TangoErrorException e) {
Log.e(TAG, getString(R.string.exception_tango_error), e);
}
}
});
}

Updating value in parse table

I am using parse.com cloud in my android application. i want to increase a field by one
I tried using three ways.
first i tried getting object using parseQuery.get(id) but it gives no object found for update after using parseObject.increament().
ParseQuery<ParseObject> parseQuery = ParseQuery.getQuery("Waive");
try {
ParseObject object=parseQuery.get(id);
object.increment("numberOfViews");
object.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException arg0) {
// TODO Auto-generated method stub
if(arg0==null){
Log.e("incremented", "by one");
}
else{
Log.e("not incremented", "by one");
arg0.printStackTrace();
}
}
});
} catch (ParseException e) {
// TODO Auto-generated catch block
Log.e("exception", e+"");
e.printStackTrace();
}
second way i used.i tried using ParseObject.increament but it gives no object found for update.
ParseQuery< ParseObject> query=new ParseQuery<ParseObject>("Waive");
query.getInBackground(id, new GetCallback<ParseObject>() {
#Override
public void done(ParseObject object, ParseException e) {
// TODO Auto-generated method stub
Log.e("object id", object+"");
if(e==null && object!=null){
object.increment("numberOfViews");
try {
object.save();
} catch (ParseException exp) {
// TODO Auto-generated catch block
Log.e("exception", exp.getMessage());
exp.printStackTrace();
}
}
}
});
}
third way i tried ,first of all i get the value of that field then increamented that value by one and inserted that value in table by using parseObject.put
ParseQuery< ParseObject> query=new ParseQuery("Waive");
query.getInBackground(id, new GetCallback() {
#Override
public void done(ParseObject object, ParseException e) {
// TODO Auto-generated method stub
Log.e("object id", object+"");
if(e==null && object!=null){
int tmp=(Integer)object.getNumber("numberOfViews");
object.put("numberOfViews", tmp+1);
try {
object.save();
} catch (ParseException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
Log.e("exception", e1.getMessage());
e1.printStackTrace();
}
}
}
});
}
but neither of these three is working please help me out.
It is due to the permission issues. Because you are trying to update a value you are not authorized for. Make it public by editing your table security on parse.com make it public writable to update by another user too

Adobe CQ : Regarding Session in Event Listener

I have a question regarding event listener. We have a event listener which listen to delete node event and perform some activity say "send email".
While code review i found this, although this code is working fine i am not convinced with the session being handled here :
#Activate
protected void activate(ComponentContext context) {
try{
final String path="/content/dam/";
Session session = repository.loginAdministrative(repository.getDefaultWorkspace());
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(this, Event.PROPERTY_REMOVED, path, true, null, null, true);
checkOutProperty = OsgiUtil.toString(context.getProperties()
.get(ASSET_LOCK_PROPNAME_UPDATE), ASSET_LOCK_PROPNAME_DEFAULT);
if (session != null && session.isLive()) {
session.save();
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:" + e.getMessage());
}
}catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured in activate method of Property Removed Listener class:"+e.getMessage());
}
}
}
#Deactivate
protected void deactivate(ComponentContext componentContext) {
try {
if (observationManager != null) {
observationManager.removeEventListener(this);
}
} catch (RepositoryException e) {
if(LOG.isErrorEnabled()){
LOG.error("Error Occured " + e);
}
} catch (Exception e) {
if(LOG.isErrorEnabled()){
LOG.error(e.getMessage());
}
}
}
Questions:
Best practice would be to create session object private to this class and should be logout in deactivate method?
Once an event is added in Observation Manager, do we really need session object? I was expecting if we should logout from session there.
EventListener are a bit cumbersome here. I fought many battles with JCR Sessions and Sling ResourceResolvers within them. The problem is, you need to keep the Session active as long as the Event Listener is active. So the only thing missing in your code is a logout on deactivate.
I created an AbstractEventListener which takes care of this and provides the following two methods and has two private members:
private Session session;
private ObservationManager observationManager;
protected void addEventListener(final EventListener eventListener,
final int eventTypes, final String path, final String[] nodeTypes) {
try {
session = getRepositorySession();
observationManager = session.getWorkspace().getObservationManager();
observationManager.addEventListener(eventListener, eventTypes,
path, true, null, nodeTypes, true);
} catch (RepositoryException e) {
LOGGER.error("Repository error while registering observation: ", e);
}
}
protected void removeEventListener(final EventListener eventListener) {
if (observationManager != null) {
try {
observationManager.removeEventListener(eventListener);
} catch (RepositoryException e) {
LOGGER.error(
"Repository error while unregistering observation: ", e);
} finally {
logoutSession(session);
}
}
}
And then in the actual EventListener I just call them:
protected void activate(ComponentContext context) {
addEventListener(this, Event.PROPERTY_ADDED| Event.PROPERTY_CHANGED, "/content/mysite", null);
}
}
protected void deactivate(ComponentContext componentContext) {
removeEventListener(this);
}

how to create a image slideshow for blackberry?

what i am trying to do is that on click of a button in screen1, i try push the screen2 repeatedly with different images and different Transition Context.
the code is as follows
public void fieldChanged(Field field, int context)
{
if(field==slideButton)
{
for(int i=0;i<bitmaps.length;i++)
{
slideScreen = new SliderScreen(bitmaps[i]);
UiApplication.getUiApplication().pushScreen(slideScreen);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
UiApplication.getUiApplication().popScreen(slideScreen);
}
}
}
}
Problem is that nothing appears.Is there any other way to achieve this..
Fixed version of your initial idea:
public void fieldChanged(Field field, int context) {
if (field==slideButton) {
final UiApplication app = UiApplication.getUiApplication();
new Thread(new Runnable() {
public void run() {
for (int i = 0; i < bitmaps.length; i++) {
final SliderScreen slideScreen =
new SliderScreen(bitmaps[i]);
app.invokeAndWait(new Runnable() {
public void run() {
app.pushScreen(slideScreen);
}
});
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
app.invokeAndWait(new Runnable() {
public void run() {
app.popScreen(slideScreen);
}
});
}
}
}).start();
}
}
Your code did not work because the UI thread was sleeping between push and pop, so it has no time/chance to start drawing the screen. Note I moved the entire action into a separate thread. So now the main UI thread has free time to actually make drawing.

Resources