I am using AsyncTask to convert image to base64 value. The task is running in the background and the app move to next activity. How can i check the status of the AsyncTask to check if it finishes or not...
My asynctask code...
public class Asyncimg extends AsyncTask<Void, Integer, String>
{
//for converting images to base64
protected void onPreExecute (){
//disbaling sync button on converting pic to base64
}
protected String doInBackground(Void...arg0) {
Cursor cursor = mydb.getDat1();
//fetching the image location
cursor.moveToFirst();
while (!cursor.isAfterLast()) {
for( int i=0 ; i< 1 ; i++ )
{
if( cursor.getColumnName(i) != null )
{
try
{
if( cursor.getString(i) != null )
{
//saving image to bitmap
Bitmap bitmap = BitmapFactory.decodeFile(cursor.getString(cursor.getColumnIndex(DBHelper.PHOTO)));
//converting it to base64
String en= encodeToBase64( resize(bitmap,1080,1920), Bitmap.CompressFormat.JPEG,50);
Log.d("base",en);
//inserting it to table pic
mydb.insertpic(cursor.getInt(1),en);
}
}
catch( Exception ignored)
{
}
}
}
cursor.moveToNext();
}
cursor.close();
mydb.updatebin();
return null;
}
protected void onPostExecute(String result) {
}
}
How can i check its status from another activity.?
way 1 :
make a Constance class and change value on that class and in another activity check that for new value
way 2 :
use Intent and put data and value in extras then call activity
way 3 :
create and use interface listeners
way 4:(seem good way)
use EventBus library : https://github.com/greenrobot/EventBus
any time you need sen notify to another activity via :
EventBus.getDefault().post("notify param");
then handle notify in another activity :
#Subscribe(threadMode = ThreadMode.MAIN)
public void onMessageEvent("notify param") {/* Do something */};
(for more details to using EventBus look library documents on github)
By using listeners. Follow this guide. https://guides.codepath.com/android/Creating-Custom-Listeners
You can set your return variable as "Public static" , from the current Activity Class you can call the public static variable and display its value from previous class.
Note: The value would diminish if the previous activity class is refreshed or destroyed making its value to null , from it you would probably get NullPointerException
Related
I have Boolean booleanCheckAvailabilityData to check availability data in my activity to create add/remove favorite. then i create
dataFavoriteMovieById = favoriteMovieViewModel.getAllFavoriteMovieById(idMovie);
to get data by id. so i make conditional statement to check avaiability data then put the result to boolean and i use the boolean later to add or remove the favorite.
if (dataFavoriteMovieById == null) {
booleanCheckAvailabilityData = false;
} else {
booleanCheckAvailabilityData = true;
}
In the first run, it work. my dataFavoriteMovieById is null
But, after i add or remove favorite. it always always contains data (RoomTrackingLiveData).
How can i solve this...
my code link : https://github.com/komangss/Submission-Menjadi-Android-Developer-Expert/blob/master/app/src/main/java/com/dicoding/submissionmade2_1/activity/DetailMovieActivity.java
I played with your app (thanks for providing a github link) and here are my results.
Latest app version
Your latest implementation doesn't produce an NPE anymore since you use getAllFavoriteMovieById in a more consistent way. You no longer initialize a LiveData instance in FavoriteMovieRepository by yourself but delegate it to Room to do it for you. So, you won't get an NPE since Room will always create a list to return results. If there're no items, it will return an empty list. So, you can safely remove a try/catch here:
try {
favoriteMovieViewModel.getAllFavoriteMovieById(idMovie).observe(this, new Observer<List<FavoriteMovie>>() {
#Override
public void onChanged(List<FavoriteMovie> favoriteMovies) {
booleanCheckAvailabilityData = favoriteMovies.size() != 0;
}
});
} catch (NullPointerException e) {
Log.d("ini bug nya", e.getMessage());
}
Original app version
In addition to what #Paul Ost said about how favoriteMovieViewModel should be used properly (by listening to it, not using it directly), I will explain why you actually had an NPE.
In that version, you were running into a NullPointerException because you returned the favoriteMovieById LiveData before it was actually initialized in your GetFavoriteMovieByIdAsyncTask.
So, here what was happening in detail. First, once your DetailMovieActivity had been created, favoriteMovieViewModel called getAllFavoriteMovieById() as below:
DetailMovieActivity.java
...
favoriteMovieViewModel = ViewModelProviders.of(this).get(FavoriteMovieViewModel.class);
dataFavoriteMovieById = favoriteMovieViewModel.getAllFavoriteMovieById(idMovie);
...
FavoriteMovieViewModel.java
FavoriteMovieViewModel instance, in turn, delegated the call to FavoriteMovieRepository instance as below:
public LiveData<List<FavoriteMovie>> getAllFavoriteMovieById(int idMovie) {
return repository.getFavoriteMovieById(idMovie);
}
FavoriteMovieRepository.java
Finally, getFavoriteMovieById started a GetFavoriteMovieByIdAsyncTask and returned favoriteMovieById:
public LiveData<List<FavoriteMovie>> getFavoriteMovieById(int id_movie) {
new GetFavoriteMovieByIdAsyncTask(favoriteMovieDao).execute(id_movie);
return favoriteMovieById;
}
But that's wrong, since your favoriteMovieById was set to null by default, and so on the first run, you were always getting it.
Your AsyncTask was eventually setting a non-null value, but it was too late:
...
private static class GetFavoriteMovieByIdAsyncTask extends AsyncTask<Integer, Void, Void> {
...
#Override
protected Void doInBackground(Integer... integers) {
FavoriteMovieRepository.favoriteMovieById = favoriteMovieDao.getFavoriteMovieById(integers[0]);
return null;
}
}
...
From what I can see in your code - getAllFavoriteMovieById works as expected. The thing is - you are using LiveData as a return type of getAllFavoriteMovieById thus it returns not the value itself but a LiveData wrapper. But if you will try to observe this LiveData object you will(presumably since I haven't seen relevant code) receive null instead of favourite value. The only correct place to assign value to your booleanCheckAvailabilityData inside this observer(depending on your DAO code of course).
favouriteMovieViewModel.getAllFavoriteMovieById().observe(this, Observer { data ->
if (data == null) {
booleanCheckAvailabilityData = false;
} else {
booleanCheckAvailabilityData = true;
}
})
Something like that(once again it depends on your DAO code and getAllFavoriteMovieById implementation)
Hope it helps.
In ROOM Try Deleting the old TABLE before inserting the new data. In that case the old data will be deleted as we are deleting the old data
I'm just getting into Android Development using Xamarin with Visual Studio 2015 Update 3. I'm trying to create a simple spinner, but something is going very, very wrong with the order of execution in the debugger.
In shared code, I have an options class that contains common values for dropdowns, etc.
public interface IOptionsCache : INotifyPropertyChanged
{
// is not observable collection on purpose, the entire list is replaced
// when data is fetched from the server
IList<string> States {get;}
}
Also in shared code, I have a standard base type to implement INotifyPropertyChanged more easily.
public abstract class NotifyDtoBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, IEqualityComparer<T> comparer = null, [CallerMemberName] string propertyName = null)
{
comparer = comparer ?? EqualityComparer<T>.Default;
if (comparer.Equals(field, value))
{
return false;
}
field = value;
OnPropertyChanged(propertyName);
return true;
}
}
Then the actual OptionsCache looks like
public class OptionsCache : NotifyDtoBase, IOptionsCache
{
protected IList<string> _states;
public IList<string> States
{
get { return this._states; }
set { SetField(ref this._states, value); }
}
public async Task PopulateCacheAsync()
{
// TODO: fetch options from server
// for now, populate inline
this.States = new List<string>(){ "MI", "FL", "ME", ... }
}
}
These are working just fine. So, in my Activity, I new up an options class, and try and populate a drop down, but things go very wrong.
[Activity (Label = "Simple App", MainLauncher = true, Icon = "#drawable/icon")]
public class MainActivity : Activity
{
protected IOptionsCache OptionsCache;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// new OptionsCache has no options to start with
// need to call PopulateCache to get data
var options = new OptionsCache();
// When the list is populated, populate the spinners
options.PropertyChanged += (sender, args) => PopulateSpinners();
// HERE IS WHERE THINGS TO BAD!
// As I step thru the code, when I hit this line (pre-execution) and then F10 to step over, it drops into the PopulateSpinners method and this.OptionsCache == null
this.OptionsCache = options;
// populate the cache async and let the property changed event
// populate the spinners
options.PopulateCacheAsync();
}
protected void PopulateSpinners()
{
Spinner statesSpinner = FindViewById<Spinner>(Resource.Id.StatesSpinner);
// this.OptionsCache == null
ArrayAdapter<string> departureAdapter = new ArrayAdapter<string>(this, global::Android.Resource.Layout.SimpleSpinnerDropDownItem, this.OptionsCache.States.ToArray());
statesSpinner.Adapter = departureAdapter;
}
}
It seems like my assignment call to the class variable is being skipped and the next method is being invoked. Not sure if it has to do with being an async method or what's going on here...
Well, the good news is that the code does actually run correctly... when it is actually deployed to the emulator.
It would seem that the latest code does not always deploy to the emulator and you may end up debugging 'old' code. One way to tell this is happening, is that the debugger will indicate invalid lines as the next statement (eg, it may say that a blank line or a class definition is the next statement, which is obviously not correct).
https://forums.xamarin.com/discussion/45327/newest-version-of-code-not-always-deployed-when-debugging-from-xamarin-studio
I'm trying to retrieve String objects from Parse. I do able to get the objects back - but only inside the 'done' method. I wish to send the data i retrieve to another function\class. I tried to do this with some different public function in the same class or even to save the String in public field, but in the moment the callback is done, the data remains blank.
what can i do in order to keep the retrieved data?
this is my code:
public void done(List<ParseObject> parseObjects, com.parse.ParseException e) {
if (e == null) {
'myFieldArray' = new String[parseObjects.size()][3];
String text = "";
int index =0;
for(ParseObject po : parseObjects){
text = po.getString("Fact");
Toast.makeText(context,theFact, Toast.LENGTH_SHORT).show();
'myFieldArray'[index][0] = text;
index++;
}
}
Well,
after few tries, i realized that the Parse query probably goes inside the block twice - and ones when there are no objects returned - thats mean the array will be initialized again - and thats the reason its remains null.
the part i should have added is
if (e == null && parseObject.size()>0)
I am currently having trouble getting a value from an AsyncTask that gets data from a JSON connection. I have looked at a few examples, but mostly I have only seen posting results from AsyncTask.
First I have an object called Dog that only has a String, Name. I am trying to get the Name of the dog from the server.
Using the following code in my oncreate, I start the DogAsyncTask while assing in an URL called n and a Dog d_in.
Dog d_in = new Dog("DogName");
DogAsyncTask task = new DogAsyncTask(d_in);
String n = "www.dog.com";
task.execute(n);
Log.e("Out", d_in.getName());
My AsyncTask is as follows:
private class DogAsyncTask extends AsyncTask<String, Void, String> {
Dog d = null;
DogAsyncTask(Dog d){
this.d = d;
}
ProgressDialog mProgressDialog;
#Override
protected void onPostExecute(String result) {
d.setName(result);
Log.e("Dog", d.getName());
mProgressDialog.dismiss();
}
#Override
protected void onPreExecute() {
mProgressDialog = ProgressDialog.show(AsyncTestActivity.this, "Loading...", "Data is Loading...");
}
#Override
protected String doInBackground(String... name) {
//Go to url = name and then gets String below.
String outfromjson = "new dog name"; //This will be a function that gets a name from JSON
return outfromjson;
}
}
I tried using something like
Log.e("Out", task.d.getName());
but I keep getting the default name of the dog which is "DogName". How to I carry values out of AsyncTask?
OK, The thing what is happening here is:
You want to pass Dog as reference (pointers as in C / C++ / Objective-C),
and you want to reflect change in original variable using other variable.
but keep in mind that Java doesn't pass object by reference, Java passes objects by value (only value is transferred, another object is created and assigned value).
So what you can do is you can assign that result-holder object again as a value to the original object.
You can do the following,
Declare and implement an interface in your activity and then use it's methods as a callback from the onPostExecute method.
i'm continuously running into problems trying to pass an ArrayList from one Activity to another. My code is failing with a Null Pointer Exception when i try to iterate through the ArrayList in my XMLParser Class. I've put print statements into the Activity that generates the ArrayList and it looks fine. Can anyone see what i'm doing wrong or why i get a Null pointer Exception when retrieving the ArrayList?
public void onClick(View v) {
if (selItemArray[0] == null) {
Toast.makeText(getApplicationContext()," Please make a Selection ", Toast.LENGTH_SHORT).show();
} else {
Intent intent = new Intent(Recipes2.this, XMLParser.class);
Log.v("Recipes2", "selItemArray[0] before call to XML Parser : " + selItemArray[0]);
//Log.v("Recipes2", "selItemArray[1] before call to XML Parser : " + selItemArray[1]);
intent.putExtra("items_to_parse", selItemArray);
startActivityForResult(intent, 0);
}
}
public class XMLParser extends ListActivity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Bundle b = getIntent().getExtras();
//itemsToParse = b.getStringArrayList("items_to_parse");
ArrayList<String> itemsToParse = new ArrayList<String>();
itemsToParse = getIntent().getExtras().getStringArrayList("items_to_parse"); Iterator<String> iterator = itemsToParse.iterator(); while(iterator.hasNext())
Log.v("XMLParser", iterator.next().toString());
It looks like you're putting a String array, not a ArrayList<String>.
You used a string array on the "sender" side and are trying to get it back as an ArrayList on the receiver side. That won't work. Use a String array on both sides and -- if necessary -- pull it into an array list.
The procedure for passing the data is here:
Passing String array between two class in android application
To convert it to a List - simply do:
List<String> = Arrays.asList(stringArray);