I am going to make website app and load feed on my first page but the problem is the scrolling is endless, how to stop this? The scrolling is endless so I want to stop it.
public class FeedActivity extends AppCompatActivity
{
private SwipeRefreshLayout swipeLayout;
private RecyclerView listView;
private LinearLayoutManager layoutManager;
private FeedAdapter adapter;
private FeedService service;
private FeedModel model;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feed);
ActionBar actionBar = getSupportActionBar();
if(null != actionBar)
{
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setIcon(R.mipmap.ic_launcher);
}
model = new FeedModel();
adapter = new FeedAdapter(model);
service = FeedService.create(model);
layoutManager = new LinearLayoutManager(this);
swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipeLayout);
listView = (RecyclerView) findViewById(R.id.listView);
listView.setLayoutManager(layoutManager);
listView.setAdapter(adapter);
}
#Override
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
}
#Override
protected void onStart()
{
super.onStart();
model.subscribe(onDataChangedListener);
adapter.setOnItemClickListener(onItemClickListener);
swipeLayout.setOnRefreshListener(onRefreshListener);
service.fetchOlder();
}
#Override
protected void onStop()
{
super.onStop();
model.unSubscribe(onDataChangedListener);
adapter.setOnItemClickListener(null);
swipeLayout.setOnRefreshListener(null);
}
FeedModel.OnDataChangedListener onDataChangedListener = new FeedModel.OnDataChangedListener()
{
#Override
public void onFetchedAndAddedToTop(int count)
{
swipeLayout.setRefreshing(false);
adapter.notifyDataSetChanged();
}
#Override
public void onFetchedAndAddedToBottom(int count)
{
if(count == 0)
{
adapter.setFooterEnabled(false);
}
adapter.notifyDataSetChanged();
}
};
SwipeRefreshLayout.OnRefreshListener onRefreshListener = new SwipeRefreshLayout.OnRefreshListener()
{
#Override
public void onRefresh()
{
service.fetchNewer();
}
};
FeedAdapter.OnItemClickListener onItemClickListener = new FeedAdapter.OnItemClickListener()
{
#Override
public void onItemClick(View view)
{
int position = listView.getChildAdapterPosition(view);
FeedItem item = model.get(position);
Intent intent = new Intent(getApplicationContext(), PostActivity.class);
intent.putExtra("id", item.getId());
startActivity(intent);
// System.out.println("Click: "+item.getTitle());
}
};
}
You can stop scrolling in two ways
If you know how many items are refreshing for every refresh you done then make a condition to stop calling refresh when you get less items than actual.
You can simply make a condition to stop refreshing list when you don't get data from earlier refresh.
Hope this Helpful..
#Rajesh
To stop endless scrolling apply a condition.
For example for every scroll 20 results are fetched and added to the list. Then you can apply a condition
if(lastFetchedItemCount!=0&&lastFetchedItemCount%20==0){
//enable scrolling
}
else{
//disable scrolling
}
Related
In my app there is an activity that when it opens it should display data in a RecyclerView. The data is stored in a collection in Firestore but unfortunately it is only working for API 21, 22 and 23, everything above is not displaying the data (see screenshots). Also sometimes it is not showing the data on the first time the user opens the activity, only when he opens it a second time or logs out and in again (in API 21). Is this something that is known or is there something with my code? Or is there a better way to display the data of a collection in a RecyclerView?
I also noticed a strange behavior:
When I add an EditText to the layout without doing anything with it in the activity, when the user clicks on the EditText, the desired documents are then displayed as they should be. On the emulator running API 21, the data shows without having to click on the EditText, so the mentioned behavior applies for API greater 24. Can someone explain this behavior?
Any help is much appreciated!
I followed this tutorial where everything works fine:
https://www.youtube.com/watch?v=lAGI6jGS4vs
My app only targets API starting at 21.
Here is my activity with the RecyclerView:
public class PrizeGameActivity extends AppCompatActivity {
private Toolbar mToolbar;
private FirebaseFirestore db = FirebaseFirestore.getInstance();
private CollectionReference prizesRef = db.collection("Prizes");
private PrizeGameAdapter prizeGameAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prize_game);
// Sets the custom toolbar as ActionBar
mToolbar = findViewById(R.id.toolbar);
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowTitleEnabled(false);
setUpRecyclerView();
}
private void setUpRecyclerView() {
Query query = prizesRef.orderBy("text",Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Prizes> options = new FirestoreRecyclerOptions.Builder<Prizes>()
.setQuery(query, Prizes.class)
.build();
prizeGameAdapter = new PrizeGameAdapter(options);
RecyclerView recyclerView = findViewById(R.id.recycler_view_prize_game);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(prizeGameAdapter);
prizeGameAdapter.startListening();
}
#Override
protected void onStart() {
super.onStart();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
#Override
protected void onStop() {
super.onStop();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
// Makes a left to right animation when user clicks the back button of the toolbar
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home) {
onBackPressed();
return true;
}
return false;
}
// Makes a right left animation when clicking the back button
#Override
public void finish() {
super.finish();
overridePendingTransition(R.anim.slide_in_left, R.anim.slide_out_right);
}
}
Here is my Adapter:
public class PrizeGameAdapter extends FirestoreRecyclerAdapter<Prizes, PrizeGameAdapter.PrizeGameHolder> {
public PrizeGameAdapter(#NonNull FirestoreRecyclerOptions<Prizes> options) {
super(options);
}
#Override
protected void onBindViewHolder(#NonNull PrizeGameHolder holder, int position, #NonNull Prizes model) {
holder.textViewPrizeGame.setText(model.getText());
}
#NonNull
#Override
public PrizeGameHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_prize_game,parent, false);
return new PrizeGameHolder(view);
}
class PrizeGameHolder extends RecyclerView.ViewHolder {
TextView textViewPrizeGame;
public PrizeGameHolder(#NonNull View itemView) {
super(itemView);
textViewPrizeGame = itemView.findViewById(R.id.listitem_text_view_prize_game);
}
}
}
And here is my prizes class:
public class Prizes {
public Prizes (){
}
public String text;
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
public Prizes(String text) {
this.text = text;
}
}
I managed to get the desired result by adding a OnCompleteListener and then set up the RecyclerView. Here is the code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_prize_game);
Query query = prizesRef.orderBy("text",Query.Direction.ASCENDING);
FirestoreRecyclerOptions<Prizes> options = new FirestoreRecyclerOptions.Builder<Prizes>()
.setQuery(query, Prizes.class)
.build();
prizeGameAdapter = new PrizeGameAdapter(options);
query.get().addOnCompleteListener(new OnCompleteListener<QuerySnapshot>() {
#Override
public void onComplete(#NonNull Task<QuerySnapshot> task) {
if(task.isSuccessful()){
setUpRecyclerView();
}else {
}
}
});
}
private void setUpRecyclerView() {
RecyclerView recyclerView = findViewById(R.id.recycler_view_prize_game);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(prizeGameAdapter);
prizeGameAdapter.startListening();
}
#Override
protected void onStart() {
super.onStart();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
#Override
protected void onStop() {
super.onStop();
if(prizeGameAdapter != null)
{
prizeGameAdapter.startListening();
}
}
I am trying to make a layout with recyclerview something like the video. I made a recyclerview which update list after certain interval but the problem is after data update it scroll to top position automatically. I want to make something like the video. https://youtu.be/omcS-6LeKoo
I have tried with link from SO
RecyclerView scrolls to top position when change the adapter data RecyclerView notifyDataSetChanged scrolls to top position but unable to solve. below is my attempt
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerViewId);
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Toast.makeText(getApplicationContext(),"Updating",Toast.LENGTH_LONG).show();
listShow();
handler.postDelayed(this,1000);
}
},1000);
}
void listShow(){
retrofitApiCall = RetrofitInstance.getRetrofitInstance().create(RetrofitApiCall.class);
Call<ModelClass_JSONParse> getDetails = retrofitApiCall;
anime = ExtendedAnime.getAll();
getDetails.enqueue(new Callback<ModelClass_JSONParse>() {
#Override
public void onResponse(Call<ModelClass_JSONParse> call,
Response<ModelClass_JSONParse> response) {
Log.v("Res",response.toString());
getWithValues = new HashMap<>();
if (response.isSuccessful()){
list.add(mModelClass_adapter);
}
adapter = new Adapter(getApplicationContext(),list);
StaggeredGridLayoutManager layoutManager = new
StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(Call<ModelClass_JSONParse> call, Throwable t) {
Log.v("Res",call.toString());
}
});
}
These lines of code are causing the problem for you. You're setting a new adapter reference and linear layout manager reference every time of your API calling.
adapter = new Adapter(getApplicationContext(),list);
StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
To Do your desired task you need to do following steps -
Just set your LayoutManager and adapter for the first time.
Make a setDataList method in your adapter class. And set your updated list to adapter list.
And then every time of calling API set that list to setDataList and call adapter.notifyDataSetChanged() method of your adapter class.
The above steps will solve your problem. Just give it a try.
The problem is probably because of you are setting new adapter reference in network callback method onResponse(). Try setting adapter in onCreate and then update dataset in callback.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerViewId);
recyclerView.setAdapter(yourAdapter);
}
In network callback,
#Override
public void onResponse(Call<ModelClass_JSONParse> call,
Response<ModelClass_JSONParse> response) {
Log.v("Res",response.toString());
getWithValues = new HashMap<>();
if (response.isSuccessful()){
adapter.setDataSet(newDataList) //not change adapter reference,only update data set
}
}
Implement setDataSet() method in your adapter to update list like below.
class YourAdapter extends RecyclerView.Adapter<>{
priavate List<> list = new ArrayList();
public void setDataSet(newList:List<>){
list.clear();
list.addAll(newList);
notifyDataSetChanged();
}
}
Don't use adapter.notifyDataSetChanged(); method because I think your main view must be wrap content so either set a fixed height like 150dp.
Try different methods like notifyItemChanged(), notifyItemRangeChanged(), notifyItemInserted()
You are setting adapter again and again when the response is changing, so you should change list and set adapter in onCreate.
Arraylist<ModelClass_adapter> list = new Arraylist<ModelClass_adapter>;
Adapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerViewId);
//set adapter here
adapter = new Adapter(getApplicationContext(),list);
StaggeredGridLayoutManager layoutManager = new
StaggeredGridLayoutManager(1,StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapter);
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Toast.makeText(getApplicationContext(),"Updating",Toast.LENGTH_LONG).show();
listShow();
handler.postDelayed(this,1000);
}
},1000);
}
void listShow(){
retrofitApiCall = RetrofitInstance.getRetrofitInstance().create(RetrofitApiCall.class);
Call<ModelClass_JSONParse> getDetails = retrofitApiCall;
anime = ExtendedAnime.getAll();
getDetails.enqueue(new Callback<ModelClass_JSONParse>() {
#Override
public void onResponse(Call<ModelClass_JSONParse> call,
Response<ModelClass_JSONParse> response) {
Log.v("Res",response.toString());
getWithValues = new HashMap<>();
if (response.isSuccessful()){
list.clear();
list.add(mModelClass_adapter);
}
adapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(Call<CurrencyModelClass_JSONParse> call, Throwable t) {
Log.v("Res",call.toString());
}
});
}
You are setting a new adapter every time and a new layout manager response comes.
which may cause this type of problem. you need to set adapter and layout manager in onCreate. just update adapter list in response of the api.
according to this answer you need linear layout manager only.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = findViewById(R.id.recyclerViewId);
list= ArrayList<>();
adapter = new Adapter(getApplicationContext(),list);
LinearLayoutManager linearLayoutManager = new
LinearLayoutManager(context, OrientationHelper.VERTICAL, false);
recycleView.setLayoutManager(linearLayoutManager);
recyclerView.setAdapter(adapter);
handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
// Toast.makeText(getApplicationContext(),"Updating",Toast.LENGTH_LONG).show();
listShow();
handler.postDelayed(this,1000);
}
},1000);
}
void listShow(){
retrofitApiCall = RetrofitInstance.getRetrofitInstance().create(RetrofitApiCall.class);
Call<ModelClass_JSONParse> getDetails = retrofitApiCall;
anime = ExtendedAnime.getAll();
getDetails.enqueue(new Callback<ModelClass_JSONParse>() {
#Override
public void onResponse(Call<ModelClass_JSONParse> call,
Response<ModelClass_JSONParse> response) {
Log.v("Res",response.toString());
getWithValues = new HashMap<>();
if (response.isSuccessful()){
adapter.getList().add(mModelClass_adapter);
}
adapter.notifyDataSetChanged();
}
}
#Override
public void onFailure(Call<CurrencyModelClass_JSONParse> call, Throwable t) {
Log.v("Res",call.toString());
}
});
}
you can do by following way
First get the count of your current datalist
int position = datalist.size();
after adding data into datalist
call DataAdapter.notifyDataSetChanged();
then move cursor to position in recyclerview
recyclerView.scrollToPosition(position);
Happy coding...!
The code Below I seem to have done everything needed, but the recyclerview is just not being populated.
I even put the Log on OnDateChange to see if it's called, and it was called once on the LogCat after I ran it on my Galaxy S6. Also, the database is public.
RecyclerView chat_view;
EditText message_text;
CollectionReference reference = FirebaseFirestore.getInstance().collection("stage2");
Query query = reference.orderBy("timestamp");
FirestoreRecyclerAdapter<ChatMessage,ChatHolder> adapter=null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_chat);
//initializing, called below
init();
}
private FirestoreRecyclerAdapter<ChatMessage,ChatHolder> newAdapter() {
final FirestoreRecyclerOptions options = new FirestoreRecyclerOptions.Builder<ChatMessage>()
.setQuery(query,ChatMessage.class)
.setLifecycleOwner(this)
.build();
return new FirestoreRecyclerAdapter<ChatMessage, ChatHolder>(options) {
#Override
public ChatHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.chat_item,parent,false);
//if(((ChatMessage)options.getSnapshots().getSnapshot(viewType)).)
return new ChatHolder(view);
}
#Override
protected void onBindViewHolder(ChatHolder holder, int position, ChatMessage model) {
//displaying the message and users into the recyclerview
holder.user_msg.setText(model.getMessage());
holder.user_date.setText(model.getDate());
holder.user_name.setText(model.getName());
}
#Override
public void onDataChanged() {
Log.d("TAG", "YESSIR");
}
#Override
public void onError(FirebaseFirestoreException e) {
super.onError(e);
}
};
}
private void init(){
chat_view = (RecyclerView) findViewById(R.id.chat_view);
chat_view.setVerticalScrollBarEnabled(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
chat_view.setLayoutManager(layoutManager);
adapter = newAdapter();
chat_view.setAdapter(adapter);
message_text = (EditText) findViewById(R.id.message_text);
message_text.setEnabled(appUtils.isSignedIn());
findViewById(R.id.send_button).setEnabled(appUtils.isSignedIn());
}
So, there we have it, I have no idea what the problem could be at this point. I am using the most recent Firestore UI dependency as well.
It seems that you have done everything necessary..using FirestoreRecycleroptions and inflating the layout in onCreateViewHolder.
For FirestoreRecyclerAdapter to be able to have the data on the activity, then you need to listen to any changes in onStart() which is after onCreate(). Also
in onStop you can stop listening.
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
I have an activity that lags (quite severely) when it's started. The lag usually lasts for under a second, but it's noticeable and I don't want it to be.
I'm not sure what's causing it to lag, but I need to fix it so that it's smooth as butter when it's loading.
Here is the activity:
public class ProfileActivity extends AppCompatActivity {
private CoordinatorLayout coordinatorLayout;
private RecyclerView recyclerView;
private LinearLayoutManager layoutManager;
private SwipeRefreshLayout swipeRefreshLayout;
private EndlessRecyclerViewScrollListener scrollListener;
private int userId;
private User user;
private List<Object> data = new ArrayList<>();
protected UserAdapter userAdapter;
private TextView username, userNumPosts;
private ImageView userBackground, userColor, userIcon;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_profile);
// Get userId from intent
userId = getIntent().getExtras().getInt("userId");
// Check if the user is in realm db
user = getRealm().where(User.class)
.equalTo("id", userId)
.findFirst();
// Make status bar black
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
Window window = getWindow();
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
window.setStatusBarColor(Color.parseColor("#000000"));
}
if (getSupportActionBar() != null) {
// Change toolbar color to the user's chosen color
getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.parseColor("#" + user.getColor())));
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
}
coordinatorLayout = (CoordinatorLayout) findViewById(R.id.coordinatorLayout);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
swipeRefreshLayout.setRefreshing(true);
username = (TextView) findViewById(R.id.username);
userNumPosts = (TextView) findViewById(R.id.userNumPosts);
userBackground = (ImageView) findViewById(R.id.userBackground);
userColor = (ImageView) findViewById(R.id.userColor);
userIcon = (ImageView) findViewById(R.id.userIcon);
username.setText(user.getUsername());
userNumPosts.setText(user.getNumPosts());
userColor.setBackgroundColor(Color.parseColor("#" + user.getColor()));
// Add the user icon
Glide.with(this)
.load(user.getIcon())
.into(userIcon);
// Add the user background
Glide.with(this)
.load(user.getBackgroundImage())
.into(userBackground);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setNestedScrollingEnabled(false);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
userAdapter = new UserAdapter(this, data);
recyclerView.setAdapter(userAdapter);
userAdapter.setUserAdapterListener(new UserAdapter.UserAdapterListener() {
#Override
public void onRequestRefresh() {
swipeRefreshLayout.setRefreshing(true);
getUserData(1);
}
});
scrollListener = new EndlessRecyclerViewScrollListener(layoutManager) {
#Override
public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
getUserData(page);
}
};
recyclerView.addOnScrollListener(scrollListener);
getUserData(1);
}
public void getUserData(final int page) {
ApiInterface apiService = ApiClient.createService(ApiInterface.class, userAuthToken);
Call<BasicResponse> call = apiService.getUserData(userId, page);
call.enqueue(new Callback<BasicResponse>() {
#Override
public void onResponse(Call<BasicResponse> call, Response<BasicResponse> response) {
if (response.isSuccessful()) {
// Show the data
List<Message> messageData = response.body().getData();
data.addAll(messageData);
userAdapter.notifyDataSetChanged();
}
swipeRefreshLayout.setRefreshing(false);
}
#Override
public void onFailure(Call<BasicResponse> call, Throwable t) {
//
}
});
}
}
What could be causing my activity to lag when it's being loaded? Should I be putting all of my main code in onCreate()?
You have too much process in onCreate(). try to move some method to onResume(). In other words, you are blocking your UI with your data processing. Then, in layout, please minimized the use of nested layout. If the layout have to many children, the app will render it slower. Also consider designing/loading your UI before the data. This would allow your user to see something, even if its not complete.
P/s : Consider moving your Data/Process to an AsyncTask. or Thread
I have look for solution too, this is worked for me
overridePendingTransition(0,0);
before starting the lagging activity.
I have a ListView which I populate with data from DataStore or from my local database.
I am checking some condition that will determine whether I will fetch data from the DataStore or database. When I fetch from the database the ListView automatically refreshes itself, but when I fetch from the DataStore it does not. I then have to click my TextView, which is below ListView, and when I click it the soft keyboard appears and then my ListView is populated with data from DataStore.
My activity that has the ListView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xyz);
list_View = (ListView) findViewById(R.id.data_listView);
list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list_View.setMultiChoiceModeListener(new Selector());
adapter = new MyAdapter(context,Long.valueOf(id),isOnline());
list_View.setAdapter(adapter);
list_View.setSelection(adapter.getCount() - 1);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
list_View.setSelection(adapter.getCount() - 1);
}
LoadDataTask ldt = new LoadDataTask();
ldt.execute("123456789");
}
private void loadDataFromDataStore(final Long contactId){
final ArrayList<Data> data = new ArrayList<>();;
d("loadingdataFromDatasore");
GetDataTask task = new GetDataTask(new ApiTask.ResultListener() {
#Override
public void successHook(Object o) {
if (o instanceof GetDataResponse) {
GetDataResponse res = (GetDataResponse) o;
if (res.getData() != null && res.getData().getItems() != null) {
for (ListDataItem i : res.getData().getItems()) {
Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1);
adapter.addFromOtherThread(dp);
}
}
d("Messages loaded from server: " + adapter.getCount());
}
}
}
public class LoadDataTask extends AsyncTask<String,String,Void> {
#Override
protected Void doInBackground(String... params){
if(isOnline && isFirstTime){
loadDataFromDataStore(Long.valueOf(params[0]));
}else{
//load from database
}
return null;
}
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
}
}
My adapter class that extends BaseAdapter (I have removed unnecessary code for this question):
public class DataAdapter extends BaseAdapter {
private ArrayList<Data>data_list;
public DataAdapter(){
data_list = new ArrayList<>();
}
public void addFromOtherThread(Data object) {
data_list.add(object);
}
What am I missing that is making listview not to automatically refresh itself even after calling notifyDatasetChanged()?
change :
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
}
}
to:
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
list_View.setAdapter(adapter);
}
}
Let me know if more clarification is required by commenting below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xyz);
list_View = (ListView) findViewById(R.id.data_listView);
list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list_View.setMultiChoiceModeListener(new Selector());
adapter = new MyAdapter(context,Long.valueOf(id),isOnline());
list_View.setAdapter(adapter);
list_View.setSelection(adapter.getCount() - 1);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
list_View.setSelection(adapter.getCount() - 1);
}
loadDataFromDataStore("123456789")
}
private void loadDataFromDataStore(final Long contactId){
final ArrayList<Data> data = new ArrayList<>();;
d("loadingdataFromDatasore");
new GetDataTask(new ApiTask.ResultListener() {
#Override
public void successHook(Object o) {
if (o instanceof GetDataResponse) {
GetDataResponse res = (GetDataResponse) o;
if (res.getData() != null && res.getData().getItems() != null) {
for (ListDataItem i : res.getData().getItems()) {
Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1);
adapter.addFromOtherThread(dp);
}
}
d("Messages loaded from server: " + adapter.getCount());
adapter.notifyDatasetChanges();
}
}
}.execute();
}
GetDataTask should work on background internally you don't need to starts a AsyncTask from here.
If you want to use AsyncTask then your AsyncTask should wait for the result from GetDataTask which it is not doing in your code implementation.
I don't know which kind of framework you are using to making api call but your implementation seems to look wrong.
I have write the code on assumption bases if your GetDataTask is a AsyncTask or some background processor it will work perfectly.