Save Instance in Android Fragment - android

I have a Fragment called HomeFragment.java. This is the first fragment that is launched when my app is opened. Inside this fragment, I have a method called "onAsyncTaskDoInBackground" that gets all the data from the server using JSON.
What i am trying to do is use "savedInstanceState" so that every time the "HomeFragment.java" is reopened not to re-download all the data.
Example:
The user opens the app and the Homefragment.java is launched, all the data is downloaded. The user goes to the about us page and returns to the Home page (Homefragment,java) all the data is downloaded again. (There should be no need to re-download all the data on the same app launch)
HomeFragment.java
public class HomeFragment extends Fragment implements OnItemClickListener, OnClickListener, MainActivity.OnLocationListener {
private View viewInflate;
DisplayImageOptions options;
ArrayList<Store> storeList;
ArrayList<News> newsList;
private ArrayList<News> arrayData;
MGAsyncTask task;
Queries q;
private Store store;
Random rand = new Random();
public HomeFragment() { }
#SuppressLint("InflateParams")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
viewInflate = inflater.inflate(R.layout.fragment_home, null);
return viewInflate;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}
#Override
public void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
if(task != null)
task.cancel(true);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onViewCreated(view, savedInstanceState);
options = new DisplayImageOptions.Builder()
.showImageOnLoading(UIConfig.SLIDER_PLACEHOLDER)
.showImageForEmptyUri(UIConfig.SLIDER_PLACEHOLDER)
.showImageOnFail(UIConfig.SLIDER_PLACEHOLDER)
.cacheInMemory(true)
.cacheOnDisk(true)
.considerExifParams(true)
.bitmapConfig(Bitmap.Config.RGB_565)
.build();
storeList = new ArrayList<Store>();
newsList = new ArrayList<News>();
MainActivity main = (MainActivity) getActivity();
timer();
main.showSwipeProgress();
main.getDebugKey();
q = main.getQueries();
if(MGUtilities.isLocationEnabled(getActivity())) {
if(MainActivity.location == null) {
main.setOnLocationListener(this);
}
else {
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
getData();
arrayData = q.getNews();
}
}, Config.DELAY_SHOW_ANIMATION);
}
}
else {
main.setOnLocationListener(this);
}
}
public void getData() {
task = new MGAsyncTask(getActivity());
task.setMGAsyncTaskListener(new OnMGAsyncTaskListener() {
#Override
public void onAsyncTaskProgressUpdate(MGAsyncTask asyncTask) {
}
#Override
public void onAsyncTaskPreExecute(MGAsyncTask asyncTask) {
asyncTask.dialog.hide();
}
#Override
public void onAsyncTaskPostExecute(MGAsyncTask asyncTask) {
// TODO Auto-generated method stub
arrayData = q.getNews();
if(!MGUtilities.hasConnection(getActivity())) {
ArrayList<Store> stores = q.getStoresFeatured();
ArrayList<News> news = q.getNews();
if (Config.HOME_STORE_FEATURED_COUNT != -1 && Config.RANK_STORES_ACCORDING_TO_NEARBY) {
Log.v("myApp", "STORE SLIDER THING - STORE SLIDER THING - STORE SLIDER THING - STORE SLIDER THING - STORE SLIDER THING - STORE SLIDER THING - " );
int storeCount = stores.size() < Config.HOME_STORE_FEATURED_COUNT ?
stores.size() : Config.HOME_STORE_FEATURED_COUNT;
if (MainActivity.location != null) {
for (Store store : stores) {
Location locStore = new Location("Store");
locStore.setLatitude(store.getLat());
locStore.setLongitude(store.getLon());
double userDistanceFromStore = MainActivity.location.distanceTo(locStore) / 1000;
store.setDistance(userDistanceFromStore);
}
Collections.sort(stores, new Comparator<Store>() {
#Override
public int compare(Store store, Store t1) {
if (store.getDistance() < t1.getDistance())
return -1;
if (store.getDistance() > t1.getDistance())
return 1;
return 0;
}
});
}
storeList = new ArrayList<Store>();
for (int x = 0; x < storeCount; x++) {
storeList.add(stores.get(x));
}
} else {
storeList = stores;
}
if (Config.HOME_NEWS_COUNT != -1 && Config.RANK_STORES_ACCORDING_TO_NEARBY) {
Log.v("myApp", "NEWS SLIDER THING - NEWS SLIDER THING - NEWS SLIDER THING - NEWS SLIDER THING - NEWS SLIDER THING - NEWS SLIDER THING - " );
int newsCount = news.size() < Config.HOME_NEWS_COUNT ? news.size() : Config.HOME_NEWS_COUNT;
newsList = new ArrayList<News>();
for (int x = 0; x < newsCount; x++) {
newsList.add(news.get(x));
}
} else {
newsList = news;
}
}
MainActivity main = (MainActivity) getActivity();
main.hideSwipeProgress();
}
#Override
public void onAsyncTaskDoInBackground(MGAsyncTask asyncTask) {
// TODO Auto-generated method stub
if( MGUtilities.hasConnection(getActivity()) && MainActivity.location != null) {
try {
UserAccessSession accessSession = UserAccessSession.getInstance(getActivity());
String strUrl = "";
if(accessSession.getFilterDistance() == 0) {
Log.v("myApp", "STRURL - STRURL - STRURL - STRURL - STRURL - STRURL - STRURL - STRURL - STRURL - STRURL - " );
if(MGUtilities.hasConnection(getActivity())) {
try {
strUrl = String.format("%s?api_key=%s",
Config.GET_CATEGORIES_JSON_URL,
Config.API_KEY);
DataParser parser = new DataParser();
Data data = parser.getData(strUrl);
MainActivity main = (MainActivity) getActivity();
if (main == null)
return;
Queries q = main.getQueries();
if (data == null)
return;
q.deleteTable("categories");
if (data.getCategories() != null && data.getCategories().size() > 0) {
Log.v("myApp", "CATEGORYS - CATEGORYS - CATEGORYS - CATEGORYS - CATEGORYS - CATEGORYS - CATEGORYS - CATEGORYS - " );
for (Category cat : data.getCategories()) {
q.insertCategory(cat);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
strUrl = String.format("%s?api_key=%s&lat=%f&lon=%f&radius=%f&news_count=%d&featured_count=%d&default_store_count_to_find_distance=%d",
Config.GET_HOME_STORES_NEWS_JSON_URL,
Config.API_KEY,
MainActivity.location.getLatitude(),
MainActivity.location.getLongitude(),
accessSession.getFilterDistance(),
Config.HOME_NEWS_COUNT,
Config.HOME_FEATURED_COUNT,
Config.DEFAULT_STORE_COUNT_TO_FIND_DISTANCE);
}
else {
strUrl = String.format("%s?api_key=%s&lat=%f&lon=%f&radius=%f&news_count=%d&default_store_count_to_find_distance=%d",
Config.GET_HOME_STORES_NEWS_JSON_URL,
Config.API_KEY,
MainActivity.location.getLatitude(),
MainActivity.location.getLongitude(),
accessSession.getFilterDistance(),
Config.HOME_NEWS_COUNT,
Config.DEFAULT_STORE_COUNT_TO_FIND_DISTANCE);
}
DataParser parser = new DataParser();
Data data = parser.getData(strUrl);
MainActivity main = (MainActivity) getActivity();
if (main == null)
return;
Queries q = main.getQueries();
if (data == null)
return;
if(Config.AUTO_ADJUST_DISTANCE) {
if(data.getMax_distance() > 0) {
UserAccessSession.getInstance(getActivity()).setFilterDistanceMax(data.getMax_distance());
}
if(UserAccessSession.getInstance(getActivity()).getFilterDistance() == 0) {
UserAccessSession.getInstance(getActivity()).setFilterDistance(data.getDefault_distance());
}
}
if (data.getStores() != null && data.getStores().size() > 0) {
Log.v("myApp", "ENTERED THE IF - ENTERED THE IF - ENTERED THE IF - ENTERED THE IF - ENTERED THE IF" );
int storeCount = data.getStores().size() < Config.HOME_STORE_FEATURED_COUNT ?
data.getStores().size() : Config.HOME_STORE_FEATURED_COUNT;
int x = 0;
for (Store store : data.getStores()) {
Location locStore = new Location("Store");
locStore.setLatitude(store.getLat());
locStore.setLongitude(store.getLon());
double userDistanceFromStore = MainActivity.location.distanceTo(locStore) / 1000;
store.setDistance(userDistanceFromStore);
if (userDistanceFromStore < 50){
Log.v("myApp", "STORE - STORE - STORE - STORE - STORE - STORE - STORE - STORE - STORE - STORE - STORE- STORE" );
q.deleteStore(store.getStore_id());
q.insertStore(store);
if(x < storeCount) {
Log.v("myApp", "if(x < storeCount) - if(x < storeCount)- if(x < storeCount)- if(x < storeCount)- if(x < storeCount)- if(x < storeCount)" );
if (store.getFeatured() == 3 ) {
storeList.add(store);
x += 1;
}
}
if (store.getPhotos() != null && store.getPhotos().size() > 0) {
Log.v("myApp", "PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS - PHOTOS" );
for (Photo photo : store.getPhotos()) {
q.deletePhoto(photo.getPhoto_id());
q.insertPhoto(photo);
}
}
}}
if (data.getNews() != null && data.getNews().size() > 0) {
Log.v("myApp", "NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS - NEWS" );
int newsCount = data.getNews().size() < Config.HOME_NEWS_COUNT
? data.getNews().size() : Config.HOME_NEWS_COUNT;
x = 0;
for (News news : data.getNews()) {
q.deleteNews(news.getNews_id());
q.insertNews(news);
if(x < newsCount) {
newsList.add(news);
x += 1;
}
}
}}
try {
strUrl = "";
strUrl = String.format("%s?api_key=%s",
Config.GET_NEWS_JSON_URL,
Config.API_KEY);
Log.v("myApp", "NEWS UPDATE - NEWS UPDATE - NEWS UPDATE - NEWS UPDATE - NEWS UPDATE - NEWS UPDATE - NEWS UPDATE " );
parser = new DataParser();
data = parser.getData(strUrl);
main = (MainActivity) getActivity();
if (main == null)
return;
if (data == null)
return;
q.deleteTable("news");
if (data.getNews() != null && data.getNews().size() > 0) {
for (News news : data.getNews()) {
q.insertNews(news);
}
}
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
task.execute();
}
#Override
public void onDestroyView() {
super.onDestroyView();
if (viewInflate != null) {
ViewGroup parentViewGroup = (ViewGroup) viewInflate.getParent();
if (parentViewGroup != null) {
MGSlider slider = (MGSlider) viewInflate.findViewById(R.id.slider);
slider.pauseSliderAnimation();
parentViewGroup.removeAllViews();
}
}
handler.removeCallbacks(runnable);
if(task != null)
task.cancel(true);
}
Handler handler = new Handler();
int apple = 0;
Runnable runnable = new Runnable() {
public void run() {
if(apple < 5) {
timer();
}
}
};
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
MGSlider slider = (MGSlider) viewInflate.findViewById(R.id.slider);
slider.stopSliderAnimation();
switch(v.getId()) { }
}
#Override
public void onResume() {
// TODO Auto-generated method stub
super.onResume();
MGSlider slider = (MGSlider) viewInflate.findViewById(R.id.slider);
slider.resumeSliderAnimation();
}
#Override
public void onPause() {
// TODO Auto-generated method stub
super.onPause();
MGSlider slider = (MGSlider) viewInflate.findViewById(R.id.slider);
slider.pauseSliderAnimation();
}
#Override
public void onLocationChanged(Location prevLoc, Location currentLoc) {
MainActivity main = (MainActivity) getActivity();
main.setOnLocationListener(null);
getData();
}
}

You can do that like below.
private View viewFragment;
private ArrayList<MyClass> list = new ArrayList<>();
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
viewFragment = inflater.inflate(R.layout.fragment_layout, container, false);
initIds();
if (savedInstanceState == null) {
// get all data and saved in list.
} else {
// use saved list or other data here...
list = savedInstanceState.getParcelableArrayList("arraylist");
setListAdapter(list);
}
return viewFragment;
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelableArrayList("arraylist", list);
}

Related

Recyclerview Inconsistency detected. Invalid view holder adapter positionViewHolder

In my app right now I am working with two lists. One is a List of an Object and the other the a List of Lists of the same object. I have a method in my Activity that transforms a list of Object into a List of Lists of object. And to my adapter I am passing the list of lists through this call:
mAdapter.swap(transformList(pipe.mList));
The method swap is responsible for passing the transformed list to my Adapter:
public void swap(List<List<Feed>> feedList) {
if (finallist == null) {
finallist = new ArrayList<>();
}
finallist.clear();
finallist.addAll(feedList);
}
The transformation checks if there are images in a row and puts all of them inside a single list (I am trying to implement something similar to WhatsApp image grouping). So I have a bunch of messages, they can be text messages, files, images, etc. In case of the last one, I group them in a single list.
Let me give a scenario as an example:
I have four images and 1 text message in my original array. The transformation puts all the four images into a single List of objects and de text message in another list of objects (both of them are inserted in my list of lists).
I thought about two ways to handle this transformation: 1 - do it inside the Adapter and 2 - do it in my Activity and pass the modified list to the Adapter. Each one of this solutions generated a different problem.
By following the steps in 1, I was able to display all of the content almost in the way I wanted. The grouping was working just fine! The problem is that if the original array had a length equals to 30, and the transformed array's length was decreased to 12. The RecyclerView would show all of the remaining 18 items as empty states (so after the transformation it wasn't handling the removing items properly).
By following the steps in 2, I was not able to display all of the content. Just the first element of my array. And I would get a IndexOutOfBoundsException in RecyclerView happens java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder error message. But I was not able to identify the problem. I checked many questions here and none of them helped me.
This is my Adapter class:
public class FeedAdapter extends BaseSkeletonAdapter<Feed> implements FeedHolder.FeedHolderListener{
private static final int HOLDER_COMMENT = 1;
private static final int HOLDER_IMAGE = 2;
private static final int HOLDER_FILE = 3;
private static final int HOLDER_AUDIO = 4;
private static final int HOLDER_MARKER = 5;
private static final int HOLDER_EMPTY = 6;
private static final int HOLDER_GROUP = 7;
private final FeedItemListener mListener;
private final int mAvatarSize;
private final String mUserId;
private final int mPictureSize;
private final int mSkeletonColor;
public static List<List<Feed>> finallist;
public FeedAdapter(FeedItemListener listener, String userId, int avatarSize, int pictureSize, int skeletonColor) {
super(2);
mListener = listener;
mUserId = userId;
mAvatarSize = avatarSize;
mPictureSize = pictureSize;
mSkeletonColor = skeletonColor;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case HOLDER_COMMENT:
case HOLDER_IMAGE:
case HOLDER_FILE:
case HOLDER_MARKER:
case HOLDER_AUDIO:
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_feed, parent, false);
return new FeedHolder(view, this, mPictureSize);
case HOLDER_GROUP:
System.out.println("É um grupo!!!");
View viewGroup = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_feed_group,parent,false);
return new FeedHolder(viewGroup, this, mPictureSize);
case HOLDER_EMPTY:
default:
View empty = LayoutInflater.from(parent.getContext()).inflate(R.layout.adapter_empty, parent, false);
return new EmptyPlaceholderViewHolder(empty, R.string.placeholder_feed_empty_title, R.string.placeholder_feed_empty_description, R.drawable.ic_feed_placeholder);
}
}
#Override
protected void onBind(RecyclerView.ViewHolder holder, int position) {
if(!(holder instanceof EmptyPlaceholderViewHolder)){
//Feed feed = finallist.get(position).get(0);
if (holder instanceof FeedHolder) {
if (position < finallist.size()) {
if (mUserId.equals(finallist.get(position).get(0).getCreatedById())) {
((FeedHolder) holder).onBind(finallist.get(position), mUserId, mAvatarSize);
} else {
((FeedHolder) holder).onBind(finallist.get(position), mUserId, mAvatarSize);
}
}
}
}
}
#Override
protected void onBind(RecyclerView.ViewHolder holder, int position, List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
}else {
if (holder instanceof FeedHolder) {
((FeedHolder) holder).onBind(finallist.get(position), payloads, mUserId, mAvatarSize);
}
}
}
#Override
protected void setHolderSkeleton(RecyclerView.ViewHolder holder) {
if (holder instanceof FeedHolder) {
((FeedHolder) holder).setHolderSkeleton(R.drawable.rounded_skeleton, mSkeletonColor);
}
}
#Override
protected void clearHolderSkeleton(RecyclerView.ViewHolder holder) {
if (holder instanceof FeedHolder) {
((FeedHolder) holder).clearHolderSkeleton();
}
}
#Override
public int getItemViewType(int position) {
if(mSkeletonMode){
return HOLDER_COMMENT;
} if (finallist != null && finallist.size() > 0 && position >= 0 && position < finallist.size()) {
System.out.println("Tamanho total: " + finallist.size());
if (finallist.get(position).size() > 1) {
System.out.println("Tamanho do grupo: " + finallist.get(position).size());
return HOLDER_GROUP;
} else {
Feed feed = finallist.get(position).get(0);
if (feed != null) {
String type = feed.getFeedType();
if (type != null) {
switch (type) {
case FEED_IMAGE:
return HOLDER_IMAGE;
case FEED_AUDIO:
return HOLDER_AUDIO;
case FEED_FILE:
return HOLDER_FILE;
case FEED_MARKER:
return HOLDER_MARKER;
case FEED_COMMENT:
default:
return HOLDER_COMMENT;
}
}
}
}
return HOLDER_COMMENT;
}else {
System.out.println("Tá vazia!");
return HOLDER_EMPTY;
}
}
public List<Feed> getItems() {
return returnList(finallist);
}
public List<List<Feed>> getListItems() {
return finallist;
}
public void swap(List<List<Feed>> feedList) {
if (finallist == null) {
finallist = new ArrayList<>();
}
finallist.clear();
finallist.addAll(feedList);
}
#Override
public void toggleLike(final int pos){
if(mListener != null && pos >= 0 && pos < finallist.size()){
mListener.toggleLike(finallist.get(pos).get(0));
}
}
#Override
public void onLongClick(final int pos, final View v) {
if (mListener != null && pos >= 0 && pos < finallist.size()) {
mListener.onLongClick(finallist.get(pos).get(0), v);
}
}
#Override
public int onAudioActionClicked(final int pos, final int progress) {
if (mListener != null) {
return mListener.onAudioActionClicked(pos, finallist.get(pos).get(0), progress);
}else {
return 0;
}
}
#Override
public void onClick(int pos) {
if (finallist!=null && pos >= 0 && pos<finallist.size()) {
Feed feed = finallist.get(pos).get(0);
if (feed != null && mListener != null) {
mListener.onClick(feed);
}
}
}
public interface FeedItemListener {
void toggleLike(#NonNull Feed feed);
void onLongClick(#NonNull Feed feed, #NonNull View v);
void onClick(#NonNull Feed feed);
int onAudioActionClicked(int pos, #NonNull Feed feed, final int progress);
}
private void transformList(List<Feed> mItems) {
finallist = new ArrayList<>();
for (int i = 0; i< mItems.size();i++) {
List<Feed> feed = new ArrayList<>();
feed.add(mItems.get(i));
finallist.add(feed);
}
int j = 0;
List<String> list = new ArrayList<>();
List<Integer> indexList = new ArrayList<>();
//System.out.println("Tamanho: " + mItems.size());
for (int i = 0; i < mItems.size(); i++) {
if (!mItems.get(i).getFeedType().equals("filePicture")) {
if (j >= 4) {
String temp = "";
for (int k = 0; k < j; k++) {
temp = temp + "->" + Integer.toString(i - (k+1));
if (k != 0) {
finallist.get(i - 1).add(finallist.get(i - (k + 1)).get(0));
indexList.add(i - (k+1));
}
}
list.add(temp);
}
j = 0;
} else {
j = j + 1;
}
if (i == mItems.size()-1) {
//System.out.println("Imagem por ultimo!");
if (j >= 4) {
//System.out.println("Grupo vem por ultimo!");
String temp = "";
for (int k = 0; k < j; k++) {
temp = temp + "->" + Integer.toString(i - (k));
if (k != 0) {
finallist.get(i).add(finallist.get(i - (k)).get(0));
indexList.add(i - (k));
}
}
list.add(temp);
}
}
}
Collections.sort(indexList);
int aux = 0;
for (int i = 0; i < indexList.size();i++) {
//System.out.println("Valor da posição: " + indexList.get(i)+ "\nTipo: "+ finallist.get((indexList.get(i).intValue())+aux).get(0).getFeedType()
// +"\nValor da posição + i: " + (indexList.get(i)+aux) + "\nAux: " + aux);
finallist.remove((indexList.get(i).intValue())+aux);
//notifyItemRangeRemoved(0, finallist.size());
//notifyDataSetChanged();
aux = aux - 1;
}
/*for (int i = 0; i< finallist.size(); i++){
if (finallist.get(i).size() > 1) {
System.out.println("groupImage: " + finallist.get(i).size());
} else {
System.out.println(finallist.get(i).get(0).getFeedType());
}
}*/
//returnList(finallist);
notifyItemRangeRemoved(0, returnList(finallist).size() - finallist.size() - 1);
//notifyItemRangeInserted(0, finallist.size());
}
public List<Feed> returnList(List<List<Feed>> lists) {
List<Feed> list = new ArrayList<>();
if (lists != null) {
for (int i = 0; i < lists.size(); i++) {
if (lists.get(i).size() > 1) {
for (int j = 0; j < lists.get(i).size(); j++) {
list.add(lists.get(i).get(j));
}
} else {
list.add(lists.get(i).get(0));
}
}
System.out.println("Tamanho de list: " + list.size());
}
return list;
}
}
And this is my Activity:
public abstract class FeedActivity extends UltraBaseActivity implements FeedAdapter.FeedItemListener, AudioManager.OnAudioFocusChangeListener, MediaPlayer.OnErrorListener, MediaPlayer.OnCompletionListener {
private static final String EXTRA_PROJECT_ID = "extra_project_id";
private static final String EXTRA_PROJECT_NAME = "extra_project_name";
private static final String EXTRA_RESOURCE_ID = "extra_resource_id";
private static final String EXTRA_RESOURCE_NAME = "extra_resource_name";
private static final String EXTRA_RESOURCE_KIND = "extra_resource_kind";
#BindView(R.id.swipeLayout) SwipeRefreshLayout mRefreshLayout;
#BindView(R.id.recyclerView) RecyclerView mRecyclerView;
#BindView(R.id.feedCreateFragment) View mFeedCreateLayout;
#BindView(R.id.mic) ImageView mMicView;
private WeakReference<FeedCreateFragment> mFeedCreateFragment;
protected FeedViewModel mViewModel;
protected FeedAdapter mAdapter;
private Feed mLongClick;
private Toolbar mToolbar;
protected int mScrollTo = -1;
protected WrapContentLinearLayoutManager mLayoutManager;
private String mPlayingFeedId;
private int mPlayingPos;
private int mActionResourcePause = R.drawable.ic_pause_black_24dp;
private int mActionResourcePlay = R.drawable.ic_play_black_24dp;
private MediaPlayer mPlayer;
private AudioManager mAudioManager;
protected Handler mAudioHandler;
protected Runnable mUpdateAudioHolderRunnable = new Runnable() {
#Override
public void run() {
try {
if (mPlayer != null && mPlayer.isPlaying()) {
notifyAdapterAudioUpdate(mPlayer.getCurrentPosition(), mActionResourcePause);
mAudioHandler.postDelayed(this, 100);
} else {
mAudioHandler.removeCallbacks(mUpdateAudioHolderRunnable);
}
} catch (IllegalStateException e){
MyLog.e(TAG, "Error while updating seed bar", e);
mAudioHandler.removeCallbacks(mUpdateAudioHolderRunnable);
}
}
};
public static void start(#NonNull Context context, #NonNull String projectId, #NonNull String projectName, #NonNull String resourceId, #NonNull String resourceName, #NonNull String resourceKind){
Intent intent = setIntent(context, projectId, projectName, resourceId, resourceName, resourceKind);
if (intent == null) return;
context.startActivity(intent);
}
public static void startForResult(#NonNull Fragment fragment, #NonNull String projectId, #NonNull String projectName, #NonNull String resourceId, #NonNull String resourceName, #NonNull String resourceKind){
Intent intent = setIntent(fragment.getContext(), projectId, projectName, resourceId, resourceName, resourceKind);
if (intent == null) return;
fragment.startActivityForResult(intent, Constants.Intents.INTENT_REQUEST_VIEW_FEED);
}
#Nullable
protected static Intent setIntent(#NonNull Context context, #NonNull String projectId, #NonNull String projectName, #NonNull String resourceId, #NonNull String resourceName, #NonNull String resourceKind) {
Intent intent;
if (resourceKind.equals(Task.ROUTE)) {
intent = new Intent(context, FeedTaskActivity.class);
}else if(resourceKind.equals(Chat.ROUTE)){
intent = new Intent(context, FeedChatActivity.class);
} else {
MyLog.e(TAG, "Error invalid resource Kind - " + resourceKind);
return null;
}
intent.putExtra(EXTRA_PROJECT_ID, projectId);
intent.putExtra(EXTRA_PROJECT_NAME, projectName);
intent.putExtra(EXTRA_RESOURCE_ID, resourceId);
intent.putExtra(EXTRA_RESOURCE_NAME, resourceName);
intent.putExtra(EXTRA_RESOURCE_KIND, resourceKind);
return intent;
}
public FeedActivity() {
super(R.layout.activity_feed);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
isLogged();
init(getIntent(), savedInstanceState);
super.onCreate(savedInstanceState);
initAdapter();
mAudioManager = (AudioManager) getSystemService(AUDIO_SERVICE);
mAudioHandler = new Handler();
mViewModel.subscribe()
.compose(this.<Resource<List<Feed>>>bindUntilEvent(ActivityEvent.DESTROY))
.flatMap(flatMapDiffUtils())
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(onNext(), onError(), onCompleted());
}
#NonNull
private Func1<Resource<List<Feed>>, Observable<FeedViewModel.Pipe>> flatMapDiffUtils() {
return new Func1<Resource<List<Feed>>, Observable<FeedViewModel.Pipe>>() {
#Override
public Observable<FeedViewModel.Pipe> call(Resource<List<Feed>> r) {
if (mViewModel.hasResource()) {
List<Feed> old = mAdapter.getItems();
MyLog.i(TAG, "New length: " + (r.data != null ? r.data.size() : 0) + " - Old: " + old.size());
final FeedDiffCallback cb = new FeedDiffCallback(old, r.data, mUser.getId());
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(cb);
return Observable.just(new FeedViewModel.Pipe(r.data, result, r.status == Status.LOADING && (r.data ==null || r.data.size() == 0)));
} else {
MyLog.i(TAG, "Loading resource from server");
return Observable.empty();
}
}
};
}
private Action1<? super FeedViewModel.Pipe> onNext() {
return new Action1<FeedViewModel.Pipe>() {
#Override
public void call(FeedViewModel.Pipe pipe) {
if (pipe != null) {
initFeedFragment();
mRefreshLayout.setRefreshing(false);
pipe.mDiffResult.dispatchUpdatesTo(mAdapter);
mAdapter.setSkeletonMode(pipe.mSkeletonMode);
//List<List<Feed>> list = new ArrayList<>();
//list = tranformList(pipe.mList);
mAdapter.swap(transformList(pipe.mList));
System.out.println("Tamanho desse troço: " + transformList(pipe.mList).size());
//mAdapter.notifyDataSetChanged();
//mAdapter.notifyItemRangeRemoved(0, pipe.mList.size());
if (mScrollTo == -1) {
mRecyclerView.scrollToPosition(mAdapter.getItemCount()-1);
}else {
mRecyclerView.scrollToPosition(mScrollTo);
}
updateMenuOptions();
showLoading(false);
}
}
};
}
protected Action0 onCompleted() {
return new Action0() {
#Override
public void call() {
MyLog.i(TAG, "Finishing feed activity");
finish();
}
};
}
protected Action1<Throwable> onError() {
return new Action1<Throwable>() {
#Override
public void call(Throwable throwable) {
MyLog.e(TAG, "Error", throwable);
}
};
}
#Override
protected void initToolbar() {
mToolbar = (Toolbar) findViewById(R.id.toolbar);
if(mToolbar !=null) {
if (mViewModel != null) {
mToolbar.setTitle(mViewModel.getProjectName());
mToolbar.setSubtitle(mViewModel.getResourceName());
}
mToolbar.setSubtitleTextColor(ContextCompat.getColor(this, R.color.palette_black));
mToolbar.setNavigationIcon(R.drawable.ic_action_back_black);
}
setSupportActionBar(mToolbar);
if (mToolbar != null) {
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onBackPressed();
}
});
}
}
protected void updateTitle(){
if(mToolbar !=null && mViewModel != null) {
mToolbar.setTitle(mViewModel.getProjectName());
mToolbar.setSubtitle(mViewModel.getResourceName());
}
}
#Override
protected void userUpdated(User user) { }
private void init(Intent i, Bundle b){
if (i != null) {
initViewModel(
i.getStringExtra(EXTRA_PROJECT_ID),
i.getStringExtra(EXTRA_PROJECT_NAME),
i.getStringExtra(EXTRA_RESOURCE_ID),
i.getStringExtra(EXTRA_RESOURCE_NAME),
i.getStringExtra(EXTRA_RESOURCE_KIND));
}else if(b != null){
initViewModel(
b.getString(EXTRA_PROJECT_ID),
b.getString(EXTRA_PROJECT_NAME),
b.getString(EXTRA_RESOURCE_ID),
b.getString(EXTRA_RESOURCE_NAME),
b.getString(EXTRA_RESOURCE_KIND));
}else {
MyLog.i(TAG, "Error while initializing view model");
finish();
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString(EXTRA_PROJECT_ID, mViewModel.getProjectId());
outState.putString(EXTRA_PROJECT_NAME, mViewModel.getProjectName());
outState.putString(EXTRA_RESOURCE_ID, mViewModel.getResourceId());
outState.putString(EXTRA_RESOURCE_NAME, mViewModel.getResourceName());
outState.putString(EXTRA_RESOURCE_KIND, mViewModel.getResourceKind());
}
private void initAdapter(){
mAdapter = new FeedAdapter(
this,
mUser.getId(),
getResources().getDimensionPixelSize(R.dimen.task_avatar_size),
(int) (AndroidUtils.getScreenWidth(this) * 0.6),
ContextCompat.getColor(this, R.color.bg_skeleton)
);
mRefreshLayout.setColorSchemeResources(R.color.yellow, android.R.color.darker_gray, R.color.yellow_edit_note, android.R.color.background_dark);
mRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
mScrollTo = -1;
mViewModel.reload();
}
});
mLayoutManager = new WrapContentLinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
}
private void initFeedFragment(){
if(!(mFeedCreateFragment != null && mFeedCreateFragment.get() != null && getSupportFragmentManager().findFragmentById(R.id.feedCreateFragment) instanceof FeedCreateFragment)){
mFeedCreateFragment = new WeakReference<>(FeedCreateFragment.newInstance(mViewModel.getProjectId(), mViewModel.getResourceId(), mViewModel.getResourceKind(), mViewModel.getResourceUsers()));
getSupportFragmentManager()
.beginTransaction()
.add(R.id.feedCreateFragment, mFeedCreateFragment.get())
.commitAllowingStateLoss();
if (mViewModel.canCreateFeed()) {
mFeedCreateLayout.setVisibility(View.VISIBLE);
}else {
mFeedCreateLayout.setVisibility(View.GONE);
}
}
}
protected abstract void initViewModel(String projectId, String projectName, String resourceId, String resourceName, String resourceKind);
protected abstract void updateMenuOptions();
}
This is part of the Error (the text reached the maximum size):
10-18 17:29:14.702 23722-23722/com.construct.test E/WrapContentLinearLayoutManager: IndexOutOfBoundsException in RecyclerView happens
java.lang.IndexOutOfBoundsException: Inconsistency detected. Invalid view holder adapter positionViewHolder{615b449 position=3 id=-1, oldPos=0, pLpos:0 scrap [attachedScrap] tmpDetached no parent}
at android.support.v7.widget.RecyclerView$Recycler.validateViewHolderForOffsetPosition(RecyclerView.java:5297)
at android.support.v7.widget.RecyclerView$Recycler.tryGetViewHolderForPositionByDeadline(RecyclerView.java:5479)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5440)
at android.support.v7.widget.RecyclerView$Recycler.getViewForPosition(RecyclerView.java:5436)
at android.support.v7.widget.LinearLayoutManager$LayoutState.next(LinearLayoutManager.java:2224)
at android.support.v7.widget.LinearLayoutManager.layoutChunk(LinearLayoutManager.java:1551)
at android.support.v7.widget.LinearLayoutManager.fill(LinearLayoutManager.java:1511)
at android.support.v7.widget.LinearLayoutManager.onLayoutChildren(LinearLayoutManager.java:595)
at com.construct.v2.adapters.WrapContentLinearLayoutManager.onLayoutChildren(WrapContentLinearLayoutManager.java:20)
My problem was caused by the BaseSkeletonAdapter<Feed> that my FeedAdapter was extending. BaseSkeletonAdapter was using the original list and not the List of Lists I had to use. So I created a new class SkeletonAdapterFeed that is basically equal to the previous one, but the new one is receiving a List of Lists instead of just the List.
I know that it sounds a little confusing. I don't have full understanding of the project I am working right now so that's why I don't know everything about the classes, etc.

Pagination doesn't work properly on list Scroll view

Following code is used for getting the new data from json on scroll of list view . But after getting the new json it does not add the new one from json instead it takes the same data that are in the first json .
Please Help me with this issue .
My Activity .
public class ProductView extends AppCompatActivity {
ListView list_product;
String json;
ProgressActivity loadingview;
int current_page = 1;
int totalPage = 1;
int Pagecount = 1;
Toolbar toolbar;
GetProductAdapter productAdapter;
List<BeanGetProducts> beanGetProductses = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_view);
toolbar = (Toolbar) findViewById(R.id.back_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ImageView img_home = (ImageView) findViewById(R.id.dr_image_home);
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ProductView.this, AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
list_product = (ListView) findViewById(R.id.list_products);
productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
list_product.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView absListView, int i) {
}
#Override
public void onScroll(AbsListView absListView, int firstItem, int visibleItemCount, int totalItem) {
int total = firstItem + visibleItemCount;
if (Pagecount < totalPage) {
if (total == totalItem) {
Pagecount++;
new getProducts(Pagecount).execute();
productAdapter.notifyDataSetChanged();
list_product.setAdapter(productAdapter);
}
}
}
});
new getProducts(current_page).execute();
}
public class getProducts extends AsyncTask<Void, Void, String> {
int pageNo;
public getProducts(int pageNo) {
this.pageNo = pageNo;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
loadingview = new ProgressActivity(ProductView.this, "");
loadingview.setCancelable(false);
loadingview.show();
} catch (Exception e) {
}
}
#Override
protected String doInBackground(Void... voids) {
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("", String.valueOf(pageNo)));
json = new ServiceHandler().makeServiceCall(GlobalLinks.mainLink + GlobalLinks.productDetails, ServiceHandler.POST, pairs);
Log.e("Parameters", "" + pairs);
return json;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingview.dismiss();
System.out.println(s);
try {
if (!Internet.isConnectingToInternet(getApplicationContext())) {
Internet.noInternet(getApplicationContext());
} else {
if (s.equalsIgnoreCase(null) || s.equalsIgnoreCase("") || s.equalsIgnoreCase("null") || s.length() == 0) {
GlobalUse.nullJSON(getApplicationContext());
} else {
JSONObject mainObject = new JSONObject(s);
boolean status = mainObject.getBoolean("status");
String message = mainObject.getString("message");
totalPage = mainObject.getInt("total_page");
Log.e("total_page", "" + totalPage);
Toast.makeText(getApplicationContext(), "" + message, Toast.LENGTH_LONG).show();
if (status == true) {
JSONArray dataArray = mainObject.getJSONArray("data");
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object = dataArray.getJSONObject(i);
JSONObject getProductObject = object.getJSONObject("GetProduct");
BeanGetProducts getProducts = new BeanGetProducts();
getProducts.setProduct_id(getProductObject.getString("product_id"));
getProducts.setImage(getProductObject.getString("image"));
getProducts.setSku(getProductObject.getString("sku"));
getProducts.setQuantity(getProductObject.getString("quantity"));
getProducts.setPrice(getProductObject.getString("price"));
getProducts.setStock_status_id(getProductObject.getString("stock_status_id"));
JSONObject product_description = object.getJSONObject("Product_Description");
getProducts.setName(product_description.getString("name"));
getProducts.setDescription(product_description.getString("description"));
JSONObject SpecialPrice = object.getJSONObject("SpecialPrice");
getProducts.setSpecialPrice(SpecialPrice.getString("price"));
beanGetProductses.add(getProducts);
}
// productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
productAdapter.notifyDataSetChanged();
list_product.setAdapter(productAdapter);
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}
Crate a new class named as EndlessScrollListener
import android.widget.AbsListView;
public abstract class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum number of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;
public EndlessScrollListener() {
}
public EndlessScrollListener(int visibleThreshold) {
this.visibleThreshold = visibleThreshold;
}
public EndlessScrollListener(int visibleThreshold, int startPage) {
this.visibleThreshold = visibleThreshold;
this.startingPageIndex = startPage;
this.currentPage = startPage;
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.currentPage = this.startingPageIndex;
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If it's still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
currentPage++;
}
// If it isn't currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (firstVisibleItem + visibleItemCount + visibleThreshold) >= totalItemCount ) {
loading = onLoadMore(currentPage + 1, totalItemCount);
}
}
// Defines the process for actually loading more data based on page
// Returns true if more data is being loaded; returns false if there is no more data to load.
public abstract boolean onLoadMore(int page, int totalItemsCount);
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}
Then change your code as below.
The pagecount which you are passing in you asynctask is actually the size of a list. So you can update this variable this after laoding data from the network.
public class ProductView extends AppCompatActivity {
ListView list_product;
String json;
ProgressActivity loadingview;
int Pagecount = 0
Toolbar toolbar;
GetProductAdapter productAdapter;
List<BeanGetProducts> beanGetProductses = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product_view);
toolbar = (Toolbar) findViewById(R.id.back_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onBackPressed();
}
});
ImageView img_home = (ImageView) findViewById(R.id.dr_image_home);
img_home.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(ProductView.this, AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
list_product = (ListView) findViewById(R.id.list_products);
productAdapter = new GetProductAdapter(beanGetProductses, ProductView.this, getApplicationContext());
// Load first time data and insert into list.
new getProducts(Pagecount).execute();
list_product.setOnScrollListener(new EndlessScrollListener() {
#Override
public boolean onLoadMore(int page, int totalItemsCount) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to your AdapterView
new getProducts(Pagecount).execute();
// or loadNextDataFromApi(totalItemsCount);
return true; // ONLY if more data is actually being loaded; false otherwise.
}
});
}
public class getProducts extends AsyncTask<Void, Void, String> {
int pageNo;
public getProducts(int pageNo) {
this.pageNo = pageNo;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
try {
loadingv
iew = new ProgressActivity(ProductView.this, "");
loadingview.setCancelable(false);
loadingview.show();
} catch (Exception e) {
}
}
#Override
protected String doInBackground(Void... voids) {
List<NameValuePair> pairs = new ArrayList<>();
pairs.add(new BasicNameValuePair("", String.valueOf(pageNo)));
json = new ServiceHandler().makeServiceCall(GlobalLinks.mainLink + GlobalLinks.productDetails, ServiceHandler.POST, pairs);
Log.e("Parameters", "" + pairs);
return json;
}
#Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
loadingview.dismiss();
System.out.println(s);
try {
if (!Internet.isConnectingToInternet(getApplicationContext())) {
Internet.noInternet(getApplicationContext());
} else {
if (s.equalsIgnoreCase(null) || s.equalsIgnoreCase("") || s.equalsIgnoreCase("null") || s.length() == 0) {
GlobalUse.nullJSON(getApplicationContext());
} else {
JSONObject mainObject = new JSONObject(s);
boolean status = mainObject.getBoolean("status");
String message = mainObject.getString("message");
totalPage = mainObject.getInt("total_page");
Log.e("total_page", "" + totalPage);
Toast.makeText(getApplicationContext(), "" + message, Toast.LENGTH_LONG).show();
if (status == true) {
JSONArray dataArray = mainObject.getJSONArray("data");
// Update Pagecount here
Pagecount = Pagecount + dataArray.length();
for (int i = 0; i < dataArray.length(); i++) {
JSONObject object = dataArray.getJSONObject(i);
JSONObject getProductObject = object.getJSONObject("GetProduct");
BeanGetProducts getProducts = new BeanGetProducts();
getProducts.setProduct_id(getProductObject.getString("product_id"));
getProducts.setImage(getProductObject.getString("image"));
getProducts.setSku(getProductObject.getString("sku"));
getProducts.setQuantity(getProductObject.getString("quantity"));
getProducts.setPrice(getProductObject.getString("price"));
getProducts.setStock_status_id(getProductObject.getString("stock_status_id"));
JSONObject product_description = object.getJSONObject("Product_Description");
getProducts.setName(product_description.getString("name"));
getProducts.setDescription(product_description.getString("description"));
JSONObject SpecialPrice = object.getJSONObject("SpecialPrice");
getProducts.setSpecialPrice(SpecialPrice.getString("price"));
beanGetProductses.add(getProducts);
productAdapter.notifyDataSetChanged();
}
}
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}
public void onBackPressed() {
Intent intent = new Intent(getApplicationContext(), AdminAccess.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
}
}

Android - RecyclerView notifyItemRemoved not working

I add an item for the progressBar at the end for loading more, and when load finish, I remove this item before adding element at the end of adapter.
But the the item is not correctly removed.
if (arrayAdapter != null) {
arrayAdapter.list.add(null);
arrayAdapter.notifyItemInserted(arrayAdapter.getItemCount() - 1);
arrayAdapter.notifyItemRangeChanged(arrayAdapter.getItemCount(), arrayAdapter.getItemCount());
}
serverRequests.getQuestionsAnsweredInBackground(userID, type, startLoad, new GetQuestionCallBack() {
#Override
public void done(ArrayList<Question> questions) {
if (arrayAdapter != null) {
arrayAdapter.list.remove(arrayAdapter.getItemCount() - 1);
arrayAdapter.notifyItemRemoved(arrayAdapter.getItemCount());
arrayAdapter.notifyItemRangeChanged(arrayAdapter.getItemCount(), arrayAdapter.getItemCount());
}
if (questions != null) {
if (arrayAdapter == null) {
arrayAdapter = new QuestionsAnsweredAdapter(getActivity(), R.layout.layout_questions_answered_item, questions, QuestionsAnswered.this);
lvQuestionsAnswered.setAdapter(arrayAdapter);
listLayout.setVisibility(View.VISIBLE);
} else {
final int positionStart = arrayAdapter.getItemCount();
arrayAdapter.list.addAll(questions);
arrayAdapter.notifyItemRangeInserted(positionStart, questions.size());
}
startLoad += questions.size();
loading = true;
}
progressBar.setVisibility(View.GONE);
}
});
Before loading new data
if(!mIsloading)
{
arrayAdapter.list.add(null);
arrayAdapter.notifyItemInserted(arrayAdapter.list.size() - 1);
mIsloading = true;
}
After done with fetching data
serverRequests.getQuestionsAnsweredInBackground(userID, type, startLoad, new GetQuestionCallBack() {
#Override
public void done(ArrayList<Question> questions) {
if (arrayAdapter.list.size() > 0 && arrayAdapter.list.get(arrayAdapter.list.size() - 1) == null) {
arrayAdapter.list.remove(arrayAdapter.list.size() - 1);
arrayAdapter.list.notifyItemRemoved(arrayAdapter.list.size());
}
mIsloading = false;
}

Android Listview Scroll position

I have a ListView and a list view adapter. The adapter populates the ListView from a List. The list view has a onScrollListener. The problem I have is when on scroll new data are loaded to the view but the scroll bar jumps to the top of the view.
What I want is to keep the scroll position where it was!
Any help?
Thanks
List View class:
private class GetItems extends AsyncTask<Void, Void, Void>
{
#Override
protected void onPreExecute() {
super.onPreExecute();
// Create a progressdialog
mProgressDialog = new ProgressDialog(AppList.this);
// Set progressdialog title
mProgressDialog.setTitle("Loading more");
mProgressDialog.setMessage("loading);
mProgressDialog.setIndeterminate(false);
// Show progressdialog
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params)
{
applicationList = new ArrayList();
try
{
GetDataAppList getDataAppList = new GetDataAppList();
JSONArray jsonData = getDataAppList.getJSONData(webfileName, limit, offset);
for (int i = 0; i <= jsonData.length() - 2; i++)
{
JSONObject c = jsonData.getJSONObject(i);
id = c.getString("id");
name = c.getString("name");
logo = c.getString("logo");
developer = c.getString("developer");
rate = c.getInt("rates");
category = c.getInt("category");
fileName = c.getString("filename");
path = c.getString("path");
appSize = c.getDouble("size");
if(category == 1001)
{
String gCat = c.getString("game_category");
applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path,gCat));
}
else
{
applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path));
}
}
JSONObject sizeObj = jsonData.getJSONObject(jsonData.length() - 1);
size = sizeObj.getInt("size");
}
catch (Exception ex)
{
Log.d("Thread:", ex.toString());
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
// Locate the ListView in listview.xml
listview = (ListView) findViewById(R.id.listView);
// Pass the results into ListViewAdapter.java
adapter = new ListViewAdapter(AppList.this, applicationList,listview);
// Binds the Adapter to the ListView
listview.setAdapter(adapter);
// Close the progressdialog
mProgressDialog.dismiss();
// Create an OnScrollListener
listview.setOnScrollListener(new OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
int threshold = 1;
int count = listview.getCount();
if (scrollState == SCROLL_STATE_IDLE) {
if (listview.getLastVisiblePosition() >= count - threshold) {
if (size >= offset)
{
new LoadMoreDataTask().execute();
offset = offset + 15;
}
else
{
Toast.makeText(getApplicationContext(), "ختم لست!", Toast.LENGTH_LONG).show();
}
}
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
// TODO Auto-generated method stub
}
});
RatingBar bar = (RatingBar) findViewById(R.id.ratingBarShow);
}
}
private class LoadMoreDataTask extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
mProgressDialog = new ProgressDialog(AppList.this);
mProgressDialog.setTitle("Loading more");
mProgressDialog.setMessage("loading);
mProgressDialog.setIndeterminate(false);
mProgressDialog.show();
}
#Override
protected Void doInBackground(Void... params)
{
try
{
GetDataAppList getDataAppList = new GetDataAppList();
JSONArray jsonData = getDataAppList.getJSONData(webfileName, limit, offset);
for (int i = 0; i <= jsonData.length(); i++) {
JSONObject c = jsonData.getJSONObject(i);
id = c.getString("id");
name = c.getString("name");
logo = c.getString("logo");
developer = c.getString("developer");
rate = c.getInt("rates");
category = c.getInt("category");
fileName = c.getString("filename");
path = c.getString("path");
appSize = c.getDouble("size");
if(category == 1001)
{
String gCat = c.getString("game_category");
applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path,gCat));
}
else
{
applicationList.add(new ApplicationPojo(id,name,logo,developer,appSize,category,fileName,path));
}
}
}
catch (Exception ex)
{
}
return null;
}
#Override
protected void onPostExecute(Void result)
{
int position = listview.getLastVisiblePosition();
adapter = new ListViewAdapter(AppList.this, applicationList,listview);
listview.setAdapter(adapter);
listview.setSelectionFromTop(position, 0);
mProgressDialog.dismiss();
}
}
The Adpater class:
public ListViewAdapter(Activity activity, ArrayList<ApplicationPojo> applicationList, ListView listView)
{
this.activity = activity;
this.applicationList = applicationList;
this.inflater = LayoutInflater.from(activity);
downloader = new ApkFileDownloader(activity);
this.listView = listView;
}
#Override
public int getCount() {
return applicationList.size();
}
#Override
public ApplicationPojo getItem(int position) {
return applicationList.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup parent)
{
if (view == null)
{
holder = new ViewHolder();
view = inflater.inflate(R.layout.singleapp, null);
holder.openInstalledAppBtn = (ImageView) view.findViewById(R.id.openInstalledApp);
holder.downloadBtn = (ImageView) view.findViewById(R.id.updateApp);
holder.progressBar = (ProgressBar)view.findViewById(R.id.updateProgress);
holder.cancelBtn = (ImageView) view.findViewById(R.id.cancel);
holder.appName = (TextView) view.findViewById(R.id.appName);
holder.developer = (TextView) view.findViewById(R.id.developer);
holder.size = (TextView) view.findViewById(R.id.size);
holder.appCat = (TextView) view.findViewById((R.id.appCat));
holder.installBtn = (ImageView) view.findViewById(R.id.install);
holder.catlogo = (ImageView) view.findViewById(R.id.catlogo);
view.setTag(holder);
}
else
{
holder = (ViewHolder) view.getTag();
}
try
{
final View finalView = view;
holder.logo = (ImageView) finalView.findViewById(R.id.appLogo);
logoName = applicationList.get(position).getLogo();
Picasso.with(activity)
.load(IPClass.SERVERIP + logoName)
.into(holder.logo);
// holder.logo.setOnClickListener(new View.OnClickListener() {
// #Override
// public void onClick(View arg0) {
//
// }
// });
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String appid = applicationList.get(position).getId();
int category = applicationList.get(position).getCategory();
Intent rec1Intent = new Intent(activity, AppView.class);
activity.startActivity(rec1Intent);
AppView appView = new AppView();
appView.setParameters(appid, category);
AppList.adapter.notifyDataSetChanged();
}
});
final String id = applicationList.get(position).getId();
final String path = applicationList.get(position).getPath();
final String fileName = applicationList.get(position).getFileName();
final String name = applicationList.get(position).getName();
final String developer = applicationList.get(position).getDeveloper();
final double size = applicationList.get(position).getSize();
final String logo = applicationList.get(position).getLogo();
final int category = applicationList.get(position).getCategory();
final String appName = applicationList.get(position).getFileName();
String checkAppInstalled = appName.substring(0,appName.length() - 4);
//------------CHECK IF APPLICATION IS INSTALLED ----------------------------------------
if(appInstalled(checkAppInstalled))
{
holder.downloadBtn.setVisibility(View.GONE);
holder.cancelBtn.setVisibility(View.GONE);
holder.progressBar.setVisibility(View.GONE);
holder.installBtn.setVisibility(View.GONE);
holder.openInstalledAppBtn.setVisibility(View.VISIBLE);
holder.openInstalledAppBtn.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v) {
String fileName = (applicationList.get(position).getFileName());
String appToOpen = fileName.substring(0,fileName.length() - 4);
Context ctx = activity.getApplicationContext();
Intent mIntent = ctx.getPackageManager().getLaunchIntentForPackage(appToOpen);
String mainActivity = mIntent.getComponent().getClassName();
Intent intent = new Intent("android.intent.category.LAUNCHER");
intent.setClassName(appToOpen, mainActivity);
activity.startActivity(intent);
}
});
}
//------------- IF APPLICATION IS NOT ALREADY INSTALLED --------------------------------
else
{
//------------------------ CHECK IF APK EXISTS -------------------------------------
String filePath = Environment.getExternalStorageDirectory().toString();
File file = new File(filePath + "/appsaraai/" + fileName);
if(file.exists())
{
holder.downloadBtn.setVisibility(View.GONE);
holder.cancelBtn.setVisibility(View.GONE);
holder.openInstalledAppBtn.setVisibility(View.GONE);
holder.progressBar.setVisibility(View.GONE);
holder.installBtn.setVisibility(View.VISIBLE);
holder.installBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/appsaraai/" + fileName)), "application/vnd.android.package-archive");
activity.startActivity(intent);
for (int i = 0; i < DownloadLists.list.size(); i++) {
if (DownloadLists.list.get(i).getName().equals(name)) {
DownloadLists.list.remove(i);
}
}
}
});
AppList.adapter.notifyDataSetChanged();
}
//------------------ IF APK DOES NOT EXIST -----------------------------------------
else
{
//-----CHECK IF DOWNLOAD IS IN PROGRESS ----------------------------------------
if (ApkFileDownloader.applicationList.containsKey(name))
{
holder.downloadBtn.setVisibility(View.GONE);
holder.installBtn.setVisibility(View.GONE);
holder.openInstalledAppBtn.setVisibility(View.GONE);
new ApkFileDownloader(activity).getDownloadStatus(holder.progressBar, name, holder.installBtn, holder.cancelBtn);
holder.progressBar.setVisibility(View.VISIBLE);
holder.cancelBtn.setVisibility(View.VISIBLE);
holder.cancelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
downloader.cancelDownload(name);
holder.cancelBtn.setVisibility(View.GONE);
holder.downloadBtn.setVisibility(View.VISIBLE);
DownloadLists dlist = new DownloadLists(activity);
dlist.deleteData(name);
try {
AppList.adapter.notifyDataSetChanged();
} catch (Exception ex) {
System.out.println(ex);
}
try
{
SearchResult.adapter.notifyDataSetChanged();
}
catch (Exception ex)
{
System.out.println(ex);
}
}
});
}
//-------------- IF DOWNLOAD IS NOT IN PROGRESS START NEW DOWNLOAD -------------
else
{
holder.progressBar.setVisibility(View.GONE);
holder.cancelBtn.setVisibility(View.GONE);
holder.installBtn.setVisibility(View.GONE);
holder.openInstalledAppBtn.setVisibility(View.GONE);
holder.downloadBtn.setVisibility(view.VISIBLE);
holder.downloadBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
holder.downloadBtn.setVisibility(View.GONE);
holder.cancelBtn.setVisibility(View.VISIBLE);
holder.cancelBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
downloader.cancelDownload(name);
holder.cancelBtn.setVisibility(View.GONE);
holder.downloadBtn.setVisibility(View.VISIBLE);
try {
AppList.adapter.notifyDataSetChanged();
} catch (Exception ex) {
System.out.println(ex);
}
try {
SearchResult.adapter.notifyDataSetChanged();
} catch (Exception ex) {
System.out.println(ex);
}
}
});
new Thread(new Runnable() {
#Override
public void run() {
try {
Bitmap logoImg = Picasso.with(activity).load(IPClass.SERVERIP + logo).get();
DownloadLists.list.add(new ApplicationPojo(id, name, developer, size, logoImg, holder.progressBar));
DownloadLists dlist = new DownloadLists(activity);
dlist.insertData(id, name, developer, size, fileName, logoImg);
UpdateServerDownload d = new UpdateServerDownload();
d.updateDownloadNo(id, category);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
new ApkFileDownloader(activity).setParameters(path, fileName, name);
try {
AppList.adapter.notifyDataSetChanged();
} catch (Exception ex) {
System.out.println(ex);
}
try {
SearchResult.adapter.notifyDataSetChanged();
} catch (Exception ex) {
System.out.println(ex);
}
}
});
}
}
}
holder.appName.setText(applicationList.get(position).getName());
holder.developer.setText(applicationList.get(position).getDeveloper());
String sizeText = " میگابایت ";
String appSize =String.valueOf(applicationList.get(position).getSize()) + sizeText;
holder.size.setText(appSize);
if(category == 1001)
{
String cat = applicationList.get(position).getgCat();
holder.appCat.setText(" " + returnGameCat(cat));
holder.catlogo.setImageResource(R.drawable.gamecatlogo);
}
}
catch (Exception ex)
{
Log.d("Adapter Exception", ex.toString());
}
return view;
}
//--------------- A METHOD TO CHECK IF APPLICATION IS ALREADY INSTALLED ------------------------
public boolean appInstalled(String checkApp)
{
pm = activity.getPackageManager();
try
{
pm.getPackageInfo(checkApp, PackageManager.GET_ACTIVITIES);
isAppInstalled = true;
}
catch (PackageManager.NameNotFoundException e)
{
isAppInstalled = false;
}
return isAppInstalled;
}
You are doing wrong in your GetItems and LoadMoreDataTask AsyncTask. you are setting new adapter each time when you scroll down so when new data are loaded to the view the scroll bar jumps to the top of the view.
You need to call
adapter = new ListViewAdapter(AppList.this, applicationList,listview);
listview.setAdapter(adapter);
only first time then you have to only call
adapter.notifyDataSetChanged()
to update your ListView no need to set adapter each time when making new request and also you have to set OnScrollListener to ListView only one time currently new OnScrollListener is set each time when making new request.
You need to setAdapter first time when adapter is null or you are fetching data first time after it just call notifyDataSetChanged()
Save state of listview before updating and then restore:
// save index and top position
int index = mListView.getFirstVisiblePosition();
View v = mListView.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
// notify dataset changed or re-assign adapter here
// restore the position of listview
mListView.setSelectionFromTop(index, top);
The most Optimal Solution will be
// Save the ListView state (= includes scroll position) as a Parceble
Parcelable state = listView.onSaveInstanceState();
// e.g. set new items
listView.setAdapter(adapter);
// Restore previous state (including selected item index and scroll position)
listView.onRestoreInstanceState(state);
Reference : Retain Scroll Position Android ListView

how to get user online or offline in asmack, android [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
XMPP aSmack - How can I get the current user state (offline/online/away/etc.)?
I am developing chat app on Android base on asmack lib. I display all the user on the ListView but I use an image to show online/offline user. But It return offline image only, even the user is online, here is my code
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.buddies);
Controller.getInstance().roster = Controller.getInstance().connection.getRoster();
// ArrayList<Buddy> buddies = new ArrayList<Buddy>();
Collection<RosterEntry> entries = Controller.getInstance().roster.getEntries();
Controller.getInstance().buddyList = new Buddy[entries.size()];
int i = 0;
for (RosterEntry r : entries) {
Buddy bud = new Buddy();
VCard card = new VCard();
try {
ProviderManager.getInstance().addIQProvider("vCard",
"vcard-temp", new VCardProvider());
card.load(Controller.getInstance().connection, r.getUser());
} catch (XMPPException e) {
Log.e("ChatOnAndroid", e.getMessage() + " " + r.getUser() + " "
+ e.getLocalizedMessage());
}
bud.jid = r.getUser();
bud.name = r.getName();
bud.status = Controller.getInstance().roster.getPresence(r.getUser());
Controller.getInstance().buddies.add(bud);
Controller.getInstance().buddyList[i++] = bud;
}
BuddyAdapter adapter = new BuddyAdapter(this, R.layout.buddy, Controller.getInstance().buddies);
setListAdapter(adapter);
/*
* list = (ListView) findViewById(R.id.buddiesList);
* list.setAdapter(adapter);
*/
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
startActivity(new Intent(this, Conferences.class));
}
public class BuddyAdapter extends ArrayAdapter<Buddy> {
private ArrayList<Buddy> items;
public BuddyAdapter(Context context, int textViewResourceId,
ArrayList<Buddy> items) {
super(context, textViewResourceId, items);
this.items = items;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.buddy, null);
}
Buddy buddy = items.get(position);
if (buddy != null) {
TextView tt = (TextView) v.findViewById(R.id.buddyName);
ImageView iv = (ImageView) v.findViewById(R.id.buddyThumb);
//buddy.status = Controller.getInstance().roster.getPresence(buddy.jid);
if (buddy.status != null) {
buddy.img = R.drawable.status_online;
iv.setImageResource(buddy.img);
} else if (buddy.status == null) {
buddy.img = R.drawable.status_offline;
iv.setImageResource(buddy.img);
}
//iv.setImageResource(buddy.img);
if (tt != null) {
tt.setText(buddy.name);
}
}
return v;
}
}
You can get online and offline friends via RosterListener like i did below and then update listview with new data.
roster.addRosterListener(new RosterListener() {
#Override
public void presenceChanged(final Presence presence) {
System.out.println("Presence changed: " + presence.getFrom()
+ " " + presence);
runOnUiThread(new Runnable() {
public void run() {
// / To Update listview should clear arraylists first
// then inavalidate Listview to redraw then add new data
// to Arraylists then notify adapter.
JID.clear();
Names.clear();
Status.clear();
Image.clear();
list.invalidateViews();
for (RosterEntry entry : entries) {
card = new VCard();
presencek = roster.getPresence(entry.getUser());
try {
card.load(Main.conn, entry.getUser());
} catch (Exception e) {
e.printStackTrace();
}
JID.add(entry.getUser());
Names.add(card.getField("FN"));
Status.add(presencek.getType().name());
Log.d("Prescence", "" + presencek.getType().name());// //num
// one
// log
// if (bud.name == null)
// bud.name = bud.jid;
// buddies.add(bud);
byte[] img = card.getAvatar();
if (img != null) {
int len = img.length;
Image.add(BitmapFactory.decodeByteArray(img, 0,
len));
} else {
Drawable d = getApplicationContext()
.getResources().getDrawable(
R.drawable.save);
Bitmap bitmap = ((BitmapDrawable) d)
.getBitmap();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100,
stream);
img = stream.toByteArray();
int len = img.length;
Image.add(BitmapFactory.decodeByteArray(img, 0,
len));
// Image.add(null);
}
// buddyList[i++] = bud;
}
adapter.notifyDataSetChanged();
}
#Override
public void entriesUpdated(Collection<String> addresses) {
// TODO Auto-generated method stub
}
#Override
public void entriesDeleted(Collection<String> addresses) {
// TODO Auto-generated method stub
}
#Override
public void entriesAdded(Collection<String> addresses) {
// TODO Auto-generated method stub
}
});
There is a means to find the offline/online status of the user. It can be done by seeking the PRESENCE OF THE USER. Here is the code snippet :
//here is how you can get is ONLINE or OFFLINE
Presence availability = roster.getPresence(user);
And here is the code to get its presence mode i.e if user is available then is he AWAY,DONOT DISTURB MODE or ONLINE For CHAT.
public int retrieveState_mode(Mode userMode, boolean isOnline) {
int userState = 0;
/** 0 for offline, 1 for online, 2 for away,3 for busy*/
if(userMode == Mode.dnd) {
userState = 3;
} else if (userMode == Mode.away || userMode == Mode.xa) {
userState = 2;
} else if (isOnline) {
userState = 1;
}
return userState;
}
you can save this state in an array list as :-
mFriendsDataClass.friendState = retrieveState_mode(availability.getMode(),availability.isAvailable());
Please let me know if you have any queries regarding xmpp/smack in chat type application

Categories

Resources