I have two methods which I need to run asynchronously in android.First I want to run getContactsList() and then populateList().I tried to use Asynctask but it skips the recyclerview populating code and then prints the next line in the log while it works well in onCreate.Please help me
private class TaskOne extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
Log.i("do in background", "running");
getContactList();
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
pDialog.cancel();
Log.i("onPostExecute", "running");
populateList();
isContacts_fetched();
Log.i("populateList", "finished");
}
}
calling in onCreate() methods
new TaskOne().execute();
populateList() code
public void populateList() {
Log.i("Populate List","Entered");
// Toast.makeText(this,String.valueOf(Common.selectedContactNos.size()),Toast.LENGTH_LONG).show();
displayRecyclerAdapter = new DisplayRecyclerAdapter(DisplayContacts.this);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(this);
recyclerView_contacts.setAdapter(displayRecyclerAdapter);
recyclerView_contacts.setLayoutManager(mLinearLayoutManager);
displayRecyclerAdapter.notifyDataSetChanged();
}
Related
In my Android app I use AAC.
Here my activity:
public class AddTraderActivity extends AppCompatActivity {
AddTraderViewModel addTraderViewModel;
private static final String TAG = AddTraderActivity.class.getName();
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
AddTraderActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.add_trader_activity);
binding.setHandler(this);
init();
}
private void init() {
ViewModelProvider viewViewModelProvider = ViewModelProviders.of(this);
addTraderViewModel = viewViewModelProvider.get(AddTraderViewModel.class);
Observer<String> () {
#Override
public void onChanged (String message){
Debug.d(TAG, "onChanged: message = " + message);
Toast.makeText(AddTraderActivity.this, message, Toast.LENGTH_LONG).show();
}
});
}
public void onClickStart() {
EditText baseEditText = findViewById(R.id.baseEditText);
EditText quoteEditText = findViewById(R.id.quoteEditText);
addTraderViewModel.doClickStart(baseEditText.getText().toString(), quoteEditText.getText().toString());
}
}
Here my ViewModel:
public class AddTraderViewModel extends AndroidViewModel {
private MutableLiveData<String> messageLiveData = new MutableLiveData<>();
private static final String TAG = AddTraderViewModel.class.getName();
public AddTraderViewModel(#NonNull Application application) {
super(application);
}
public void doClickStart(String base, String quote) {
Debug.d(TAG, "doClickStart: ");
if (base.trim().isEmpty() || quote.trim().isEmpty()) {
String message = getApplication().getApplicationContext().getString(R.string.please_input_all_fields);
messageLiveData.setValue(message);
return;
}
}
public LiveData<String> getMessageLiveData() {
return messageLiveData;
}
}
So when I click on button on Activity call method onClickStart()
If any fields is empty the show toast. In the activity call method:
onChanged (String message)
Nice. It's work fine.
But the problem is, when I rotate the device in the activity method onChanged(String message) is called AGAIN and as result show toast. This happened on every rotation.
Why?
This is the expected behaviour. If you want to avoid this you must set message = "" and keep an empty check before showing the toast.
A better way to use it is something like Event Wrapper or SingleLiveEvent
Highly recommend you to read this article. This explains why you are facing this and what are your options in detail.
I am using Room Database with LiveData , but my Local Database is updating too fast as per our requirement and at the same time i have to reload my recycler view .instead of calling notifyDataSetChanged() to adapter , i am trying to use DiffUtil , but is crashing or not reloading properly , this is uncertain .
i am following this tutorial :
Tutorials Link here
MyAdapter :
public class SwitchGridAdapter extends RecyclerView.Adapter<SwitchGridAdapter.ViewHolder> {
private List<Object> allItemsList;
private LayoutInflater mInflater;
private OnItemClickListener mClickListener;
private Context context;
private Queue<List<Object>> pendingUpdates =
new ArrayDeque<>();
// data is passed into the constructor
public SwitchGridAdapter(Context context,List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList) {
this.mInflater = LayoutInflater.from(context);
this.context = context;
allItemsList = new ArrayList<>();
if (applianceList!=null) allItemsList.addAll(applianceList);
if (zmoteRemoteList!=null)allItemsList.addAll(zmoteRemoteList);
}
// inflates the cell layout from xml when needed
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = mInflater.inflate(R .layout.switch_grid_item, parent, false);
return new ViewHolder(view);
}
// binds the data to the textview in each cell
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// Doing some update with UI Elements
}
// total number of cells
#Override
public int getItemCount() {
return allItemsList.size();
}
// stores and recycles views as they are scrolled off screen
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,View.OnLongClickListener {
TextView myTextView;
ImageView imgSwitch;
ViewHolder(View itemView) {
super(itemView);
myTextView = (TextView) itemView.findViewById(R.id.txtSwitchName);
imgSwitch = (ImageView) itemView.findViewById(R.id.imgSwitchStatus);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
// handling click
}
#Override
public boolean onLongClick(View view) {
return true;
}
// convenience method for getting data at click position
Object getItem(int id) {
return allItemsList.get(id);
}
// allows clicks events to be caught
public void setClickListener(OnItemClickListener itemClickListener) {
this.mClickListener = itemClickListener;
}
// parent activity will implement this method to respond to click events
public interface OnItemClickListener {
void onItemClick(View view, int position);
void onItemLongPressListner(View view, int position);
}
// ✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
// From This Line Reloading with Diff Util is Done .
//✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅✅
public void setApplianceList( List<Appliance> applianceList,List<ZmoteRemote> zmoteRemoteList)
{
if (allItemsList == null)
allItemsList = new ArrayList<>();
List<Object> newAppliances = new ArrayList<>();
if (applianceList!=null) newAppliances.addAll(applianceList);
updateItems(newAppliances);
}
// when new data becomes available
public void updateItems(final List<Object> newItems) {
pendingUpdates.add(newItems);
if (pendingUpdates.size() > 1) {
return;
}
updateItemsInternal(newItems);
}
// This method does the heavy lifting of
// pushing the work to the background thread
void updateItemsInternal(final List<Object> newItems) {
final List<Object> oldItems = new ArrayList<>(this.allItemsList);
final Handler handler = new Handler();
new Thread(new Runnable() {
#Override
public void run() {
final DiffUtil.DiffResult diffResult =
DiffUtil.calculateDiff(new DiffUtilHelper(oldItems, newItems));
handler.post(new Runnable() {
#Override
public void run() {
applyDiffResult(newItems, diffResult);
}
});
}
}).start();
}
// This method is called when the background work is done
protected void applyDiffResult(List<Object> newItems,
DiffUtil.DiffResult diffResult) {
dispatchUpdates(newItems, diffResult);
}
// This method does the work of actually updating
// the backing data and notifying the adapter
protected void dispatchUpdates(List<Object> newItems,
DiffUtil.DiffResult diffResult) {
// ❌❌❌❌❌❌ Next Line is Crashing the app ❌❌❌❌❌
pendingUpdates.remove();
dispatchUpdates(newItems, diffResult);
if (pendingUpdates.size() > 0) {
updateItemsInternal(pendingUpdates.peek());
}
}
}
Observing LiveData
public void setUpAppliancesListLiveData()
{
if (applianceObserver!=null)
{
applianceObserver = null;
}
Log.e("Appliance Fetch","RoomName:"+this.roomName);
applianceObserver = new Observer<List<Appliance>>() {
#Override
public void onChanged(#Nullable List<Appliance> applianceEntities) {
// Log.e("Appliance Result","Appliance List \n\n:"+applianceEntities.toString());
new Thread(new Runnable() {
#Override
public void run() {
List<Appliance> applianceListTemp = applianceEntities;
zmoteRemoteList = new ArrayList<>(); //appDelegate.getDatabase().zmoteRemoteDao().getRemoteList(roomName);
// Sort according to name
Collections.sort(applianceListTemp, new Comparator<Appliance>() {
#Override
public int compare(Appliance item, Appliance t1) {
String s1 = item.getSwitchName();
String s2 = t1.getSwitchName();
return s1.compareToIgnoreCase(s2);
}
});
if(getActivity()!=null) {
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
applianceList = applianceListTemp;
mRecyclerView.getRecycledViewPool().clear();
adapter.setApplianceList(applianceList,zmoteRemoteList);
}
});
}
}
}).start();
}
};
appDelegate.getDatabase().applianceDao().getApplinaceListByRoomName(this.roomName).observe(this, applianceObserver);
}
I have a class AsyncTask as an inner class to a fragment.
public class MyAsyncTask extends AsyncTask<String,double[],double[]> {
double posScoreb = 0.0;
double negScoreb= 0.0;
public AsyncResponse delegate = null;
#Override
protected void onPreExecute() {
progressBar.setVisibility(View.VISIBLE);}
#Override
protected double[] doInBackground(String... params) {
s = new SentiCalc(getActivity().getAssets());
s.setInput(String.valueOf(params[0]));
double[] set = new double[]{};
try {
set = s.getSenti();
} catch (IOException e) {
e.printStackTrace();
}
posScoreb = set[1];
negScoreb = set[2];
return new double[]{posScoreb,negScoreb};
}
#Override
protected void onPostExecute(double[] result) {
progressBar.setVisibility(View.GONE);
result[0] = posScoreb;
result[1] = negScoreb;
delegate.processFinish(result);
Toast.makeText(getActivity(), "Done",Toast.LENGTH_LONG).show();
}
}
I am calling it from a method saveNote() inside the same fragment.`
asyncTask = new MyAsyncTask() ;
asyncTask.delegate =this;
asyncTask.execute(content);
I want AsyncTask class to return values inside a result(double array) to saveNote method. As shown in this, How to get the result of OnPostExecute() to main activity because AsyncTask is a separate class?.
I created an interface and made my fragment class to implement it.
public interface AsyncResponse {
void processFinish(double[] output);}
As a result of which I am able to get the result inside a method processFinish
within the same fragment.
#Override
public void processFinish(double[] output) {
double posScore,negScore;
posScore = output[0];
negScore = output[1];
Toast.makeText(getActivity(),String.valueOf(posScore),Toast.LENGTH_LONG).show();
Toast.makeText(getActivity(), String.valueOf(negScore), Toast.LENGTH_LONG).show();
}
How can I get this result inside a saveNote method from which I am calling AsyncTask class?
I am trying to finish this program and i am stuck. This is my first program and now it wont work. I keep getting this error when i add query.fromLocalDatastore(); The code runs fine until i try to get it from the local storage. This is telling me there is nothing there for it to retrieve and i don't know why. When i added my test data it worked fine but when i try to pull data from another table i get the error above. Apparently when i added the test data the server synced with the local datastore. Now it is not. Can someone tell me what I did wrong?
public class DataHolder extends Application {
int age;
#Override
public void onCreate() {
super.onCreate();
Parse.enableLocalDatastore(getApplicationContext());
Parse.initialize(this,key, key);
ParseUser.enableAutomaticUser();
ParseACL defaultACL = new ParseACL();
ParseACL.setDefaultACL(defaultACL, true);
}
public class MainActivity extends ActionBarActivity implements Disclaimer.DisclaimerListener {
protected void continueToRun() {
spinner1.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> adapter, View v, int x, long lng) {
final ParseQuery<ParseObject> query = ParseQuery.getQuery("Phone_Numbers");
query.fromLocalDatastore();
if (x == 1) {
final Intent intent = new Intent(getBaseContext(), Protocol_Template.class);
query.fromLocalDatastore();
query.whereEqualTo("objectId", "uGANULyrdL");
startActivity(intent);
}
}
public class Protocol_Template extends Activity {
DataHolder global;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_protocol__template);
final TextView protocol = (TextView) findViewById(R.id.txt02);
findViewById(R.id.btn2timesUpperLeft);
final ParseQuery<ParseObject> query = ParseQuery.getQuery("Phone_Numbers");
query.fromLocalDatastore();
query.getFirstInBackground(new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
final String protocols = object.get("PhoneNumber").toString();
protocol.setText(protocols);
} else {
protocol.setText(e.getMessage());
}
}
});
}
I have a customized gridview where i'm checking onScroll method to find the end of the list. If the scroll reaches the end of the list, it will again add few elements in to the list.
gridview.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView arg0, int arg1) {
}
#Override
public void onScroll(AbsListView arg0, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
int lastInScreen = firstVisibleItem + visibleItemCount;
//is the bottom item visible & not loading more already ? Load more !
if((lastInScreen == totalItemCount) && (!loadingMore))
{
new LoadDataTask().execute();
}
}
});
And this is my Asynchronous task class..
private class LoadDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
if (isCancelled()) {
return null;
}
loadingMore = true;
for (int i = 0; i < mNames.length; i++)
mListItems.add(mNames[i]);
return null;
}
#Override
protected void onPostExecute(Void result) {
mListItems.add("Added after load more");
loadingMore=false;
adapter.notifyDataSetChanged();
super.onPostExecute(result);
}
#Override
protected void onCancelled() {
}
}
Now the issue is that the onScroll method keep on calling. It doesn't stop even when the user not scrolling. Can anyone have a solution ?
Please check the answer for this question: onScroll gets called when I set listView.onScrollListener(this), but without any touch .
The same is true for the GridView, since it has AbsListView as superclass just as ListView does.