Update UI widget from onPostExecute() of AsyncTask in another project - java

So, I want to display an image in an ImageView that is downloaded from a website and saved on the device's file system. The downloading of the image is done by calling a method in another class (in one of my separate library projects). This method, in turn, calls an AsyncTask to do the downloading in another thread. On the post execute of this AsyncTask, I want to set the image for the ImageView. Keep in mind that this separate library is independent of my main app and knows nothing about my UI (and I wish to keep it this way).
I have a method in the UI portion of my code (in a fragment) that sets the image for this ImageView. I'm thinking it would be nice to pass this method to the library method that retrieves the image. That way, when the download is complete, onPostExecute() could call this UI method that I have. The dilemma I'm facing is I don't want any compile-time dependencies for my library that references my UI/ImageView.
Finally, not every time when this AsyncTask is called do I want to do anything in the post execute. In other words, any post execute logic is completely optional.
General Flow:
1) Code in my fragment calls MyLib.saveRemoteFile(url, destinationFilename)
2) MyLib.saveRemoteFile() downloads the image and saves it to a file by way of a thread (via an AsyncTask)
3) As soon as the image is downloaded and saved, I want to set the ImageView.setImageBitmap() using the bitmap from the saved file
I've looked at the Command pattern, but am stuck on how to implement it in this particular scenario. Any tips on this?
Maybe there is another approach that can be used? (without MyLib.saveRemoteFile() having compile-time dependencies to the UI)?
UI Fragment code snippet:
.
boolean wasSaved = MyLib.saveRemoteFile(url, destinationFilename, true)
.
.
.
Library code snippet (in a different library project):
public static boolean saveRemoteFile(String url, String filename, boolean overwriteExistingFile)
{
.
// code to check if directory exist and creates it if needed, etc, etc...
.
.
.
new AsyncTask<String, Void, Boolean>() {
#Override
protected Boolean doInBackground(String... params)
{
// code to download and save image file...
.
.
.
}
#Override
protected void onPostExecute(Boolean result)
{
// *** this is where I want to take the ImageView and set its bitmap image.
}
}.execute(new String[] {url, filename});
return retVal;
}

Design is flawed, library should have provided you Observer design pattern, using which you would have submitted listener reference along with downloading details.
Upon finishing downloading, library using your provided listener would have notified back to you over download process result, reading which you could have taken action easily with UI.
Moreover in your library code saveRemoteFile() spawns a asynctask, return value is irrelevant here as method wont wait until asynctask is executed.
Possible implementation as per above mentioned info.
// Interface for bserving
public interface DownloadListsner{
public void onSuccess(String uri);
public void onError(String uri);
}
// API for submitting download request
public void saveRemoteFile(String url, String filename,DownloadListsner listener... ){
...
}
AsyncTask{
// Upon finish execution
onPostExecute(){
// Take action
listener.onSuccess
or
listener.onError
}
}

Command pattern
You should be rather implementing Observer pattern and your download library should allow other code to attach listeners and be notified about when certain action is completed/started/whatever. And since you are just being informed that something happened you can have your code that reacts on that notification completely different in every part of your app if you need so.

Related

Android not calling first method/skipping first method

I'm using Azure Face API for facial recognition, some of my methods are only running correctly in debug mode:
public void detectFace(MenuItem item){
getPicture();
startFaceRecognition();
}
I first noticed the issue with the code above. The getPicture() method does not seem to run if the second method is called after, though does run if the startFaceRecognition() is called from within getPicture().
public void addFace(MenuItem item){
getPicture();
AddFaceParams params = new AddFaceParams("family", "personIdCode", "", currentPhotoPath);
new AddFaceTask().execute(params);
}
The second piece of code takes a picture and then sends the picture with relevant information to Azure with a HTTP request in an asynchronous task. I believe the issue is the getPicture() method isn't being called unless there's a breakpoint placed inside the method. It works if I step through the method, but not if it is run by itself.
Would this be some form of timing issue?
I am new to Java and Android development.

Using ASyncTask for Reading from a File with Google Drive API on Android

I am using Google Drive API on an Android device.
I need to get the contents of a file on Google Drive to a string. Something simple like
String dbData = driveObject.downloadFileToString("db_export.txt");
I am implementing a "GoogleDrive" object. I need to do this without all the mess of tasks and threads and callbacks. However, I can't do it.
Here's an example: I have implemented a method called "findFileByPath" that returns the file ID of a file whose pathname is given as a parameter. However, the Android gods have forced any calls to this -- because it deals with network activity -- to happen in a thread or AsyncTask. The problem is that any pause to wait for the task to complete causes the Google Drive API threads to pause. So....if I do this:
FindFileWithAsyncTask ffwat = new FindFileWithAsyncTask();
ffwat.execute(filePath);
File f = ffwat.get(5, TimeUnits.SECONDS);
where the call to "findFileByPath" is done in a AsyncTask called "FindFileWithAsyncTask" it just hangs everything. The Google Drive API only proceeds when the "get" times out.
HELP! There has got to be a way to do this that can avoid -- or mask -- all the asynchronous BS.
Any clues? Thanks!
It's hard to get rid of AsyncTasks when using network services because otherwise your UI will freeze waiting for the result.
Try to do this:
new AsyncTask<String, Void, String>() {
#Override
protected String doInBackground(String... params) {
String dbData = driveObject.downloadFileToString("db_export.txt");
return dbData;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
File f = new File(s);
}
}.execute();
Then you will wait for the result on onPostExecute method.
And creating the AsyncTask on the fly will reduce the boring code.

Android Asynctask run one by one in order

I am trying to create a lot of asynctask, and run one by on in order.
Is it possible? I can't find any solution for this.
onPostExecute and then call a new AsnycTask again is not a good solution for me.
SO what I want:
async1.execute
async2.execute
async3.execute
async1.over->async2.start
async2.over->async3.start
If you use the serial executor (default in API 11 and above), this happens automatically. If you need this to work before API 11, you need to do the classic wait/notify trick (https://www.science.uva.nl/ict/ossdocs/java/tutorial/java/threads/waitAndNotify.html)
Do like
async1.execute
then write async2.execute into onPostexecute of async1
and then write async3.execute into onPostexecute of async2
There is no any other valid way. You can think about to implement threads (wait/notify), but that is not for asyntask.
I guess you should use Executor whit BlockQueue instead of AsyncTask, and use Handler to send handle the result. BockQueue is a FIFO data structure, and fit your flavor...
// Async Task Class here async1
class YourAsynClass extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// Shows Progress Bar Dialog and then call doInBackground method
showDialog(progress_bar_type);
}
#Override
protected String doInBackground(String... PassYourdata) {
// do your stuff here
}
#Override
protected void onPostExecute(String IFYouwantPassData) {
// Dismiss the dialog
dismissDialog(progress_bar_type);
// here async2
new SecondAsyncTask.execute(Passeddata);
}
}
and in the third one do the same
Let the first AsyncTask is MyAsyncTask1 and the second one is MyAsyncTask2. Now what you want is.
Execute the MyAsyncTask1 from with in the activity
Take the response received
Now on successfull response,execute the MyAsyncTask2
what about calling them in sequence like:
MyAsyncTask1.execute();
MyAsyncTask2.execute();
The problem with the above code can be understood by the fact that calling execute on the AsyncTask object will create a new thread to run in different memory space,and immediately the next AyncTask will be started with in its own memory space.But that was not what we want.We want that the first thread must finish its working and only then the second one will start to work.How this can be achieved?
The answer lies in the onPostExecute().This is the method which will help you to get rid of this situation.While you call execute on MyAsyncTask1 then after doInBackground() of the first AsyncTask its,onPostExecute() will be called .Place a check in that onPostExecute() that if response is null, if received response is not equal to null,and is a valid response then call execute on the MyAsyncTask2(with respective parameters if specified).
SEE THIS
You can do this in a chain.....

Java wait for method to return object

I am making a library where an application can use it to capture a selection of a screen and convert it to an image, like Gyazo.
This library is not the application itself, but only the tool that returns the File or BufferedImage object to the application.
I want the application to be simple as this:
Bootstrap b = new Boostrap(new GifCapturer());
b.beginCapture(); // user selects an area
File file = b.getFile();
But how can I make the application wait till the library returns the object? as you see the beginCapture method should activate the JFrame where the user will select an area to capture.
Do I need to sleep the thread? or use listeners design?
The beginCapture method starts a jframe window, where the user is able to select an area of the screen. Once selected, the library will convert the selected area to an object and set it as a local variable. So when you will use getFile it ill return the captured image. But the thing is, i need to make sure that the image was selected before getFile call gets executed, and wait instead but im not sure how.
Sorry if the question is not detailed, im on phone.
Please let me know if you need more information.
Implement a listener, that is invoked as soon the selection is ready. Put your File file = b.getFile(); code into the listener.
The code of your JFrame would be necessary to give a more detailed answer.
I have decided to use a Listener with a own built listener class, and interface.
Create an interface which you will use to get the data, or that will get know when the listener gets called, like this in my case:
public static void main(String[] args) throws AWTException {
Bootstrap b = new Bootstrap(new GifCapturer());
b.beginCapture(new ScreenCaptureCallback() {
#Override
public void captureEnded(File file) {
System.out.println("done!");
}
});
}

What is the correct way to handle the AQuery (android-query) download result?

Sorry if I missed something obvious, I tried really hard but didn't find any clue to answer my question.
So, my task is to download several images using their URLs and store them in some folder. I tried different approaches but for several reasons I decided I should use AQuery for this.
The download is actually done in IntentService which is started from the activity or from AlarmManager. The part where I download images is a for loop for downloading the required amount of images from the generated URLs:
for (int i=0; i < required; i++) {
url = makeURL(i);
aq.download(url, imgDir, new AjaxCallback() {
#Override
public void callback(String url, Object object, AjaxStatus status) {
super.callback(url, object, status);
File file = (File) object;
if (file.length() < 300 * 1024) { //just an example test
file.delete();
}
}
});
AQuery starts a separate thread for each download so the code continues to execute before I can get any result. The problem is that images can be broken or do not fit for other reasons so I do the test after each download in a callback method. If the image does not pass one of the tests I delete the file and need to redownload the image from another URL. But since all downloads are done in an independent threads I can't catch the result of the downloads in the same IntentService where I have all the "spare" URLs.
Since my IntentService is a background thread itself I think I can do all the downloads in that thread, check the file after each download and try another URL if it's bad.
As I understand, I have two options here:
find a way to make aq.download use the same thread
don't use AQuery and take another approach for downloading
I would be very grateful for an advice. My experience is still very limited to make the correct decision. Thanks in advance!

Categories

Resources