AsyncTask Params Object parameter - android

I know how to handle the asynctask but i have some doubt now. Pls check my aysnctask code below
public class MyAsynTask extends AsyncTask<Object, Object, Object> {
#Override
protected Object doInBackground(Object... params) {
Log.d("Main params ", "" + params[0] );
return null;
}
}
There is no issues in code and it's running. my doubt is, when i am using different parameter in execute method i am getting result. Pls refer the code below
new MyAsynTask().execute("Welcome");
new MyAsynTask().execute(10);
new MyAsynTask().execute(10.5f);
new MyAsynTask().execute(11.12d);
here am passing different types of value but my doInBackground method have object type parameter. While am passing different values how the doInBackground gives me a result. Pls explain if anyone knows.
Thanks in advance

As you know object is the super class in java so in doinBackgroung after getting params[0] you should type cast after getting that value like below
//this is for string case
String stringValue = params[0].toString();

Every time you past the parameter to doInBackground compiler casts it to object type. Every primitive type int, float, bool... have object type analogue Integer, Float, Boolean... And in this case compiler will cast it to object type analogues at first, so it would be safely cast to Object type later. Object type is superclass for all object types (it is a root for class hierarchy) and it have .toString() function, but .toString is override in child classes (Integer, Float...). And according to inheritance rules child function will be called. So integer, float... will be correctly translate to strings and print in Log.

Related

Passing a function that returns an object in Dart / Flutter does not work

I'm pretty new in Dart coding world.
I'm using Sembast (ver 2.1.1) and coding in Flutter.
I've created an abstract class called ImageItem. Then other types of images inherit from it, say a ArtworkItem class:
class ArtworkItem extends ImageItem {
DateTime lastUpdated;
String category;
ArtworkItem({
this.lastUpdated,
this.category,
);
static ArtworkItem fromMap(Map<String, dynamic> map) {
return ArtworkItem(
lastUpdated = map['last_updated'],
category = map['category'],
);
}
}
So in the code above the ArtworkItem has a static method that returns the ArtworkItem object from a map.
Then there is a class called Repository. Repository has a method that has takes a Function as a parameter, and it returns a List. Like this:
List<ImageItem> getImagesFromRepository(ImageItem Function(Map<String, dynamic) fromMap) {
// Do something here to get List of RecordSnapshot object.
// ....Additional code here
final recordSnapshots = await _store.find( await database, finder: finder, );
return recordSnapshot.map((snapshot) => fromMap(snapshot.value));
}
And when I call this method like this in a DAO file:
return getImagesFromRepository(ArtworkItem.fromMap);
I got and Exception:
'MappedListIterable<SembastRecordSnapshot<String, Map<String, dynamic>>, ImageItem>' is not a subtype of type 'List<ImageItem>'
But if I do:
return recordSnapshots
.map(
(snapshot) => ArtworkItem.fromMap(snapshot.value))
.toList();
This works, just by specifying explicitly ArtworkItem.fromMap it works. But this will defeat the purpose of abstraction.
I'll just make a wild guess that your callback isn't explicitly typed.
List<ImageItem> getImagesFromRepository(ImageItem Function(Map<String, dynamic>) fromMap) {}
DateTime is not a supported type in sembast (it uses json which does not support DateTime). lastUpdated should/could be converted to an int (millis since epoch) or an ISO8601 string.
I don't if that's the reason of your issue (I'm assuming recordSnapshot is of type List, not RecordSnapshot) and why you did not get any error before. It is hard to say whether your app is stalled as you said or whether an exception was thrown, you could try to wrap into a try/catch and print the error for debugging purpose.
#zk_regen, i think your getImagesFromRepository function is expecting incorrect parameter. I think it should expect ImageItem if you're passing an instance of ArtworkItem like so,
List<ImageItem> getImagesFromRepository(ImageItem imageItem) {
// Do something here to get List of RecordSnapshot object.

Convert Async task params

I have a method inside AsyncTask class which I want to reuse. But it uses the object of type String... url which is accessed as url[0],url[1]
To reuse this function I need create a object of Type String... or
convert String... to String[]
I did not find any documentation for String...
#Override
protected String doInBackground(String... url) {
Thread.currentThread().setName("MetaDataDownloader");
String jsonStr=metadataDownloader(url);
//this uses param as url[0] and so on
}
That is because AsyncTask by design could receive more than one parameter (hence the varargs...).
Change your method like this:
#Override
protected String doInBackground(String... urls) {
Thread.currentThread().setName("MetaDataDownloader");
// if you want to handle all URLs
if (urls != null) {
for (String url : urls) {
String jsonStr=metadataDownloader(url);
}
}
}
You can create constructor in async task and pass what argument you would like to . Do not use parameters in doInBackground.
You can look at this Java Document. It's arbitrary number of arguments.
ou can use a construct called varargs to pass an arbitrary number of values to a method. You use varargs when you don't know how many of a particular type of argument will be passed to the method. It's a shortcut to creating an array manually (the previous method could have used varargs rather than an array).
To use varargs, you follow the type of the last parameter by an ellipsis (three dots, ...), then a space, and the parameter name. The method can then be called with any number of that parameter, including none.
--> to use your doInBackground(String... url), just treat it as array of parameters and cast it to whatever you like.

How #JsonProperty working using jackson parser in android

In this below code, if I access getBl_no () its correctly returning value. I don't know how it's working I didn't set bl_no anywhere is that Json property will set to that set method? Please anyone explain.
#JsonProperty("BL_NO")
private String bl_no;
public String getBl_no() {
return bl_no;
}
public void setBl_no(String bl_no) {
this.bl_no = bl_no;
}
#JsonProperty annotation is where the magic happens! The JSON parser that you use reads the JSON property named BL_NO and assigns its value to the private instance variable bl_no. You don't even need a setBl_no() method for this to work.
#JsonProperty annotation lets you tell the JSON parser that while serializing or deserializing, the JSON property BL_NO should be tied to variable bl_no. That's how the variable gets initialized with a value even though you don't explicitly do it.

How to fetch object and array fields with Parse?

I'm unable to properly fetch a ParseObject that contains a field of type 'Object' : after changing manually the 'Object' field value in the Parse DataBrowser and then fetch the ParseObject from the app, the fetched ParseObject still provide the old value for the 'Object' field, but provide the right new value for the 'String' field.
Here is the sample code I use :
public class MainActivity extends ActionBarActivity {
ParseObject object;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
object = ParseObject.createWithoutData("Test", "tvgTg8jAXz");
}
#Override
protected void onResume() {
super.onResume();
object.fetchInBackground().onSuccess(new Continuation<ParseObject, Object>() {
#Override
public Object then(Task<ParseObject> task) throws Exception {
JSONObject data = task.getResult().getJSONObject("data");
String name = task.getResult().getString("name");
Log.d("OBJECT", data.toString());
Log.d("OBJECT", name);
return null;
}
}).continueWith(new Continuation<Object, Object>() {
#Override
public Object then(Task<Object> task) throws Exception {
if (task.getError() != null) {
Log.e("OBJECT", task.getError().getLocalizedMessage());
}
return null;
}
});
}
}
After I change both 'data' and 'name' fields in the DataBrowser, if 'onResume()' is called without a previous call to 'onCreate()' (after locking/unlocking screen for example) then the logs shows the old value for 'data' and the new value for 'name'.
This is a simple code example to highlight the problem I encounter in a bigger project.
Is this a known issue of the Parse Android SDK ? Is there a workaround ?
Thanks
Now that I learned that you have turned on the local datastore I can come with an, at least partial, answer.
Turning on the local datastore has some side effects. One being that only one instance of each object exists locally. So when you call fetchInBackground the second time, object is already populated with data. The problem then (i think) is that the API no longer override 'complex' types (pointers, objects, arrays), perhaps because it could mess up internal relationships in the data store. Since the fact that the data store will recursively save an object (and pointers) so suddenly swapping a pointer might leave objects 'hanging'. (again, only guessing).
Now I must admit that it still confuses me a bit looking at your code, cause it does not seem that you at any point write your object to the data store, however..
What should work is to unpin the object before 'refreshing' it:
object.unpinInBackground.onSuccess(new Continuation<>{
...
// when done call fetch
});
According to Parse, this is a known issue that they will not fix for now : https://developers.facebook.com/bugs/1624269784474093/
We must use the following methods to retrieve JSON objects/arrays fields from a ParseObject :
getMap() instead of getJSONObject()
getList() instead of getJSONArray()
These methods will return Map and List objects respectively.
I found that managing Map and List in my project instead of JSONObjet and JSONArray is not a problem and is even clearer.

Can somebody explain how to use ASyncTask with Android?

I've been doing a bunch of research and looking over the documentation for ASyncTask in Android, but I just can't seem to wrap my head around it. I simply want to run some methods while a fragment is visible in an application, but in order to more easily do that, I think I should be using ASyncTask. My example code is as follows:
private class syncExample extends ASyncTask <Void, Void, Void>
{
#Override
protected void onPreExecute()
{
}
#Override
protected void doInBackground(Void... voids)
{
}
#Override
protected void onProgressUpdate()
{
}
#Override
protected void onPostExecute()
{
}
}
Now my questions are as follows:
In the angle brackets, I have Void, Void, Void. What exactly do those represent and how do I know what's correct to place in there?
For each method within the class, I have the each method called as void. When should they be different than void (like boolean, String, long, etc.)?
For the doInBackground method, I have Void... voids in the parenthesis. What exactly should I be putting in there? What do they represent?
Thank you for your help. The documentation on this is not very clear for a beginner like myself.
AsyncTask uses parameterized types (java generics) so that you can specify the types it uses when you define your own AsyncTask. Perhaps it's easier to explain in this form:
public abstract class AsyncTask<Params, Progress, Result> {
...
protected abstract Result doInBackground(Params... params);
protected abstract void onProgressUpdate(Progress... progress);
protected abstract void onPostExecute(Result result);
...
}
There are no classes named Params, Progress, or Result. These are instead generic types. They are just placeholders for types you wish to use when you define your own AsyncTask subclass. The above could equally be written as such:
public abstract class AsyncTask<A, B, C> {
...
protected abstract C doInBackground(A... params);
protected abstract void onProgressUpdate(B... progress);
protected abstract void onPostExecute(C result);
...
}
Suppose I were defining an AsyncTask that takes a list of Strings representing URLs, and it will ping each one to see if it's reachable, then return the number that were reachable. Meanwhile, with each test, it will update a ProgressBar as each test completes. It might look something like this:
public class MyAsyncTask extends AsyncTask<String, Integer, Integer> {
#Override
protected Integer doInBackground(String... params) {
int total = params.length;
int successfulPings = 0;
for (int i = 0; i < total; i++) {
if (isReachable(params[i])) {
successfulPings++;
}
publishProgress(i, total);
}
return successfulPings;
}
#Override
protected void onProgressUpdate(Integer... progress) {
int testsSoFar = progress[0];
int totalTests = progress[1];
progressBar.setMax(totalTests);
progressBar.setProgress(testSoFar);
}
#Override
protected void onPostExecute(Integer result) {
Toast.makeTest(context, "Reached " + result + " sites.", Toast.LENGTH_SHORT).show();
}
}
I would initiate this as follows:
String[] urls = ...
MyAsyncTask task = new MyAsyncTask();
task.execute(urls);
The argument passed into execute will be passed into doInBackground. Whatever you do in doInBackground, you need to return something that gets passed in as the argument to onPostExecute. While in doInBackground, you can call publishProgress, where you can do something like I did (but you don't have to).
My basic suggestion is to research more about AsyncTask but I'll as well try and Answer your questions:
1- In the angle brackets, I have Void, Void, Void. What exactly do those represent and how do I know what's correct to place in there?
They are the input argument types for the overridden methods: doInBackground() onPreExecute(), onProgressUpdate() and ... respectively.
2- For each method within the class, I have the each method called as void. When should they be different than void (like boolean, String,
long, etc.)?
I'll give you an example: onPostExecute() is guaranteed to be called after doInBackground(), so if onPostExecute(int someCounter) has an integer in its input, then doInBackground() should return an integer rather than void. So it will be declared like this:
int doInBackground(){
//bla bla bla
int someIntegerValue;
return someIntegerValue;
}
3- For the doInBackground() method, I have Void... voids in the parenthesis. What exactly should I be putting in there? What do they
represent?
They are var-args, basically speaking, they represent Variable number of Arguments.
Read more about them here.
Once again I suggest you delve into threading in Android and get a sense of why AsyncTask is needed.
Good Luck,
The three types used by an asynchronous task are the following:
Params, the type of the parameters sent to the task upon execution. i.e if you want to send some variable/array to your async task background task. You use that information using that variable.
Progress, the type of the progress units published during the background computation. i.e to show the progress of your background progress. ( such as showing how much a video/image is downloaded)
Result, the type of the result of the background computation. i.e the result that you calculated in background process used for passing result to onPostExecute method.
String[] username;
username[0]="user1";
username[1]="user2";
new asynctask().execute(username);
private class asynctask extends AsyncTask <USER, Integer, String>
{
#Override
protected void onPreExecute()
{
// anything you want to do prior starting the async task.
}
#Override
protected String doInBackground(USER... users)
{
int count = users.length;
for (int i = 0; i < count; i++)
retriveinformation(users[i]);
return "Hey";
}
protected void onProgressUpdate(Integer... progress) {
setProgressPercent(progress[0]);
}
protected void onPostExecute(String result) {
// the value result is HEY that is returned by doInBackground.
}
}
Not all types are always used by an asynchronous task. To mark a type as unused, simply use the type Void.
information taken from https://developer.android.com/reference/android/os/AsyncTask.html
Let me try my hand at this. All the info I am parsing is from the link shared by Karakuri in the comments to the question.
The angle brackets' contents, in order, are called "parameters", "progress", and "result". Parameters is the type of parameters (using varargs) that will be fed to "doInBackground". They will be receive by that method in an array. You will use these parameters as your data to work on in the background thread.
"Progress" is the types of values fed into the onProgressUpdate. When you override this method, you will take in data of this type, format it, and use it in the progress display. From my reading, it is up to you to publish your progress in doInBackground to be consumed by onProgressUpdate.
"Result" is the data type of the result of the operation. This will be the return type of doInBackground, as well as the parameter type of onPostExecute.
For parameters that include the "..." (called varargs), you can put in as many arguments as you want. They must be separated by commas, and must all be of the type specified before the "...". The items will be passed to the function in an array. So, to answer your questions:
You'll change the first parameter in the angle brackets from void when your background task needs to receive data to work on. The type will be the type of data you'd like to pass in. You'll change the second parameter when you wish to keep track of the progress. The type will be whatever type you'd like to use for keeping track, and you will need to do all the tracking yourself in "doInBackground". You'll change the third parameter when your background task needs to return data. The type will be the type of data you wish to return. The data will be supplied to "onPostExecute". This is important because AsyncTask.execute() has no return value, so you must use any necessary data in that method to get it out to the class that called AsyncTask.execute().
onPreExecute appears to always be type void. doInBackground will be of the type of result, the 3rd argument in your angle brackets. onProgressUpdate appears to always be void. onPostExecute appears to be always void.
The parameter of doInBackground will be a type label followed by the three dot and a name. The type for the label must be the same as the first parameter in the angle brackets. The name is anything you want. That name will then be assigned to an array of the type named in the type label, and passed in for you to use in the body of doInBackground.
Some thoughts: if you are a beginner, leave "progress" void for now, and don't override onProgressUpdate. It is very important in production code, but a lot of extra hard work for beginner learning projects. onPreExecute is also likely more trouble than it is worth at your level. Just remember they exist, and when you need them, you will likely know. Also, good work on not avoiding the subject of multithreading just because it is difficult.

Categories

Resources