So I have a somewhat general question regarding something I came across recently. Let's say have I have 2 classes, Activity and Task. In Activity, a new Task object is instantiated, but instead of being given its usual parameters, some new code is introduced in brackets afterward, and one of its methods is called on that instantiation. I've seen methods being called on an object as soon as it is created, but not re-defining its behavior also. This is all Android based, so maybe it's related to that, but something this syntactically weird seems more like a Java concept than something that Android introduced. Here's the class file:
class Task extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... args) {
try {
//do things here
} catch (Exception ex) {
ex.printStackTrace();
Log.e("Exception", ex.toString());
}
return Text;
}
}
which is the object to be created, and then the code which instantiates it is here:
new Task() {
#Override
public void onPostExecute(String result) {
Log.d("JSON", result);
try {
if (jObject.has("error")) {
//Do something here
}
else if (!paymentCheck(appDomain)){
//do something else
}
else {
//Do last thing
}
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}.execute(appDomain, email, password);
I understand that AsyncTask is a quirky class in that it passes the result from its doInBackground method to the onPostExecute one in a separate thread, and maybe that's why this is done, but I dont really understand why you wouldn't just define onPostExecute in Tasks own class file, like I've seen with other examples. Also, this thing compiles and runs perfectly fine, doing everything it's supposed to to. I just don't really understand the reasoning behind. Hopefully someone here can help! Thanks
This is a Java syntactic sugar called an anonymous class.
I'm not an Android developer so I'm not entirely familiar with any peculiarities there, but this pattern is used whenever you need to ensure that the response action occurs in a separate thread to avoid deadlocks and the like or when the onPostExecute manipulates objects that are not visible in Task. This can act as a sort of closure over any final objects that are in scope.
Related
Say we have a lot of methods where we want to print something fx using System.out.println(...)
then we can just create a method like
public void print(String msg) {
System.out.println(...)
}
And then we can just do: print("Some message") which is faster and saves us for writing System.out.println(...) everytime.
So now to the case. I am practicing with Java I/O, which wants hell a lot of try/catch. So instead of having to write a try/catch block everytime, can I do something like
public sometype tryCatch (String objThatCanThrowExc) {
clause = "try {
" + objThatCanThrowExc + "
} catch(Exception e) {
print(e);
} "
return clause;
}
And then do something like this
public void server(int port) {
ServerSocket ss = null;
//Assume ss is not null, and client is a Socket
tryCatch("client = ss.accept();");
...
}
With the above code I am just trying to express what I want to do. I am not sure if there is something smart available to help me achieve this. Another way that could be even better is if I could do something like this
public void server(int port) {
ServerSocket ss = null;
tryCatch() {
client = ss.accept();
}
...
}
I have not much programming experience, so I know this is a silly question, but who knows, maybe there is something smart
If I understand it correctly, what you want to do is call multiple IO functions that might throw, but without writing the same "catch" logic for each.
You are right that what you want to do is somehow "pass" the code that might throw into another method that handles the catch for you. In Java, this mechanism is not strings but lambda functions.
We can use them like this:
import java.io.*;
class Main {
#FunctionalInterface
public interface Action {
void run() throws Exception;
}
private static void printExceptionAndContinue(final Action action) {
try {
action.run();
} catch(Exception error) {
System.out.println(error.toString());
}
}
public static void main(String[] args) {
printExceptionAndContinue(() -> {
// Here goes some code that might throw!
throw new Exception("Oh no!");
});
printExceptionAndContinue(() -> {
// And some more
System.out.println("Still gets called!");
});
}
}
For those saying that a "string" of code cannot be typed and interpreted in a strongly-typed compiled language, I would encourage them to look at F# quotations.
The concept that you're looking for is called a Try type. It's similar to java.util.Optional, which can be either "present" or "empty"; a Try can be either "success" or "failure". It's not built into Java, but the Vavr library is one commonly-used implementation.
In your example, the "clause" you're using is a String, so unless you try parsing it as code (which is complicated) it's not going to work.
Instead it's better to have a different return statement in the try part and in the catch part. If you get an error saying that you aren't returning anything, try putting a dummy return statement after the try/catch statements which returns null or zero or the empty string.
if the try-catch needs to work with some specific operation to an object yes. we can.
Say. we have an interface
public interface - oneOperation
public interface oneOperation{
public void execute() throws Exception;
default void invoke(){
try {
this.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
}
now the impls of the interface only implement execute() method.
Other Objects that uses the impls can call the invoke() method in case they want the exception to be not thrown
not sure if this is what you were looking for ..
So I needed a while loop that would auto-refresh the text on the layout and I finally found a way like this (I only put the important part so you get the idea) :
public void restart() {
GetRate asyncRate = new GetRate();
asyncRate.execute();
}
private class GetRate extends AsyncTask<Void, Integer, String> {
#Override
protected String doInBackground(Void... params) {
try {
String p = urlfind();
return p;
}
catch (IOException e) {
return "0";
}
}
#Override
protected void onPostExecute(String p) {
price_text.setText(p);
restart();
}
now my question is, is this a good way of getting this done or could this cause problems ? the app seems to be working fine and I am not getting any errors for the moment, if there is a better or simpler way to do this please give an answer. thanks
Edit : this turned out to be a really bad idea even when I added sleep intervals the app would work for a 15min then crash so I dont advise anyone to use this.
Instead of calling the thread manually, AlarmManager or ScheduledExecutorService could be used to fire the task at certain intervals or at certain time.
AlarmManager is generally used for large intervals and the later one for short intervals.
Using these classes, you can fire your task and get your UI updated.
I am fetching album art with the last.fm api in an asynctask class. The code works in postExecute() with latency, though it won't work at all in doInBackground().. it is not making updates to my UI at all, so i'm not sure what's going on
#Override
public Void doInBackground(String... args){
if(oslist.size()!=0) {
for (int i = 0; i < 30; i++) {
String albumURL = null;
try{
albumURL = new RetrieveAlbumArtUrlTask().execute(String.format(APIURL,
URLEncoder.encode(oslist.get(i).get(TAG_ARTIST), "UTF-8"),
URLEncoder.encode(oslist.get(i).get(TAG_ALBUM), "UTF-8"))).get();
} catch (UnsupportedEncodingException e) {
} catch (InterruptedException e) {
} catch(ExecutionException e){
}
oslist.get(i).put("albumArtUrl", albumURL);
Log.v("TEST", ""+albumURL);
}
}
return null;
}
you have 2 choices :
1. return the data you want to update to the onPostExecute and update the UI from there.. dont do long operation on the postExecute..
2.if your running this on the Activity Class you can use the RunOnUIThread function inside the doInBackground and update the UI from it.
An AsyncTask does not work in that manner Teddy. The AsyncTask is broken up into two parts. The doInBackground() segment is meant to handle non-UI components because it works outside the UI thread. When you need to make a change to UI from within the AsyncTask, you call publishProgress() with a custom identifier to distinguish what you want updated.
I often do this with an enum. Then you shall see your UI changes occurring and your non-UI components from lagging the UI. Just read up on the AsyncTask examples a bit.
I am using OpenCYC api (no too common, besides the point though), and I am trying to create an object AccessObject named ao. The problem is, for whatever reason, an AccessObject cannot be instantiated inside the main Java Swing Event Thread.
So as a workaround, I made another thread that just instantiates an AccessObject in it's run() method and also provides a getter for it to return it.
So this is what I have for the calling code:
// do something with code
AccessObject ao;
AccessObjectInstantiateThread aoThread = new AccessObjectInstantiationThread();
aoThread.start();
while(ao == null) // while loop to ensure we "wait" for aoThread to finish
{
ao = aoThread.getAoObject();
}
// Then use ao however you want
Now this code works, but it seems pretty rediculous. Is there any better way to do this? Remember, there is no way I can instantiate an AccessObject under the main java event thread.
Thank you very much, Rich.
Instantiate it in a SwingWorker object, and check for a valid object before completing the doInBackground() method.
Add a PropertyChangeWorker to the SwingWorker that listens for SwingWorker.StateValue.DONE, then pass the object to your Swing program.
For example,
class MySwingWorker extends SwingWorker<AccessObject, Void> {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
}
In your Swing code:
final MySwingWorker mySwingWorker = new MySwingWorker();
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChanged(PropertyChangeEvent pcEvt) {
if (pcEvt.getNewValue() == SwingWorker.StateValue.DONE) {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}
});
mySwingWorker.execute();
Note, code note tested nor compiled.
Edit as per JB Nizet's recommendation you could also simply do an anonymous inner class in your Swing code and skip the PropertyChangeListener:
new SwingWorker<AccessObject, Void>() {
public AccessObject doInBackground() throws Exception {
// do whatever needed to create your AccessObject and check its completion
// return your AccessObject
}
public void done() {
try {
ao = mySwingWorker.get(); // ao is an AccessObject class field
// you can use ao here
} catch (whaeverExceptionYouAreTrapping e) {
// do something with exception
}
}
}.execute();
Your code may not work. You should at least declare your variable as follows:
volatile AccessObject ao;
The reason is, your EDT thread may cache the value of ao variable as an optimization and may not see ao is assigned to a new value.
I hope this code is at the beginning of you application and users will not see UI is not responding.
Ideally you would create AccessObject ao on the start up thread (in the main() method) and not start your UI (EventQueue.InvokeLater with a runnable containing something like new JFrame) until after you had.
Failing that, make ao volatile. Your instantiation code should set this value directly rather than bothering about a "get" method. It should probably also call InvokeLater with a runnable to readjust the display--maybe enable a button or two and send the user a message that things are now possible that were not possible before.
Any code accessing ao has to be prepared for the fact that it may be null; your GUI has to work both ways, making its situation clear to the user. Every check or reference should look something like:
final AccessObject local_ao = ao;
if (local_ao != null) {
// Do things. USE local_ao, NOT oa!!!
}
In short, always use local_ao, which won't change. Remember that the value of ao can and will change at any time. As you've described it, it will only change from null to non-null, and do so only once, but that may change as your code evolves. (If it won't evolve, my first suggestion might be best.)
Your UI (EventQueue) code should not wait for anything. Threads are pain, and I'd take a little delay in the UI over using a thread any day. But you've already paid the price for a thread, so you may as well get your money's worth.
I have an app that needs to pull data from a server and insert it into an SQLite database in response to user input. I thought this would be pretty simple - the code that pulls the data from the server is a fairly straightforward subclass of AsyncTask, and it works exactly as I expect it to without hanging the UI thread. I implemented callback functionality for it with a simple interface and wrapped it in a static class, so my code looks like this:
MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
#Override
public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
// do something with contents
}
}
All still good. Even if the server takes an hour to retrieve the data, the UI still runs smoothly, because the code in getFolderContents is running in the doInBackground method of an AsyncTask (which is in a separate thread from the UI). At the very end of the getFolderContents method, the onFolderContentsResponse is called and passed the list of FilesystemEntry's that was received from the server. I only really say all this so that it's hopefully clear that my problem is not in the getFolderContents method or in any of my networking code, because it doesn't ever occur there.
The problem arises when I try to insert into a database via my subclass of ContentProvider within the onFolderContentsResponse method; the UI always hangs while that code is executing, leading me to believe that despite being called from the doInBackground method of an AsyncTask, the inserts are somehow still running on the UI thread. Here's what the problematic code looks like:
MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
#Override
public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
insertContentsIntoDB(contents);
}
}
And the insertContentsIntoDB method:
void insertContentsIntoDB(final List<FilesystemEntry> contents) {
for (FilesystemEntry entry : contents) {
ContentValues values = new ContentValues();
values.put(COLUMN_1, entry.attr1);
values.put(COLUMN_2, entry.attr2);
// etc.
mContentResolver.insert(MyContentProvider.CONTENT_URI, values);
}
}
where mContentResolver has been previously set to the result of the getContentResolver() method.
I've tried putting insertContentsIntoDB in its own Thread, like so:
MyServerCaller.getFolderContents(folderId, new OnFolderContentsResponseListener() {
#Override
public void onFolderContentsResponse(final List<FilesystemEntry> contents) {
new Thread(new Runnable() {
#Override
public void run() {
insertContentsIntoDB(contents);
}
}).run();
}
}
I've also tried running each individual insert in its own thread (the insert method in MyContentProvider is synchronized, so this shouldn't cause any issues there):
void insertContentsIntoDB(final List<FilesystemEntry> contents) {
for (FilesystemEntry entry : contents) {
new Thread(new Runnable() {
#Override
public void run() {
ContentValues values = new ContentValues();
values.put(COLUMN_1, entry.attr1);
values.put(COLUMN_2, entry.attr2);
// etc.
mContentResolver.insert(MyContentProvider.CONTENT_URI, values);
}
}).run();
}
}
And just for good measure, I've also tried both of those solutions with the relevant code in the doInBackground method of another AsyncTask. Finally, I've explicitly defined MyContentProvider as living in a separate process in my AndroidManifest.xml:
<provider android:name=".MyContentProvider" android:process=":remote"/>
It runs fine, but it still seems to run in the UI thread. That's the point where I really started tearing my hair out over this, because that doesn't make any sense at all to me. No matter what I do, the UI always hangs during the inserts. Is there any way to get them not to?
Instead of calling mContentResolver.insert(), use AsyncQueryHandler and its startInsert() method. AsyncQueryHandler is designed to facilitate asynchronous ContentResolver queries.
I think your original problem may have been that you are calling the run method on your new thread (which causes execution to continue on the current thread) instead of calling the start method. I think this is what Bright Great was trying to say in his/her answer. See Difference between running and starting a thread. It's a common mistake.
Man.Relax yourself.And anything would looks better.
At first,Start a Thread is Func start not Func run,if you want to start the new Thread
not only call the func run.
new Thread(Runnable runnable).start();
Then I bet use Handler sometimes would be better than AsyncTask.
You can run the query in the doInBackground(Integer int) overridden method of the AsynTask, and update the main UI on the onPostExecute(Integer int) method.