How to use ParseObjects with a RecyclerView? - java

I am attempting to pull data from my parse server and display an image and text within a RecyclerView of CardViews. I have encountered a few issues, some of which may not have been corrected appropriately, so please feel free to correct any novice code you find below outside of my two current issues. Finally my two issues are.
The data does not display initially. I have 3 tabs in a ViewPager and I have to swipe over twice in order for it to display. If I'm on tab 1 the data doesn't appear until I swipe to tab 3 and return to tab 1, and vice versa. Because there isn't a tab 4, tab 2 never displays.
The second issue I am currently faced with is that at times the data will not match up. It will have the picture from one row matched with the description from another entity.
Below is my MusicFragment.java
public class MusicFragment extends Fragment {
private ArrayList<String> titles = new ArrayList<>();
private ArrayList<Bitmap> bitmaps = new ArrayList<>();
private ArrayList<String> descriptions = new ArrayList<>();
private boolean notComplete = true;
public MusicFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
RecyclerView musicRecycler = (RecyclerView)inflater.inflate(
R.layout.fragment_music, container, false);
if (notComplete) {
// Get the MusicFragImages class as a reference.
ParseQuery<ParseObject> query = new ParseQuery<>("MusicFragImages");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
for (ParseObject object : objects) {
String description = (String) object.get("description");
ParseFile file = (ParseFile) object.get("image");
String title = (String) object.get("title");
titles.add(title);
descriptions.add(description);
file.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] data, ParseException e) {
if (e == null && data != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
bitmaps.add(bitmap);
}
}
});
}
} else {
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
notComplete = false;
}
// Create captioned images and registers it to the adapter.
CaptionedImagesAdapter adapter = new CaptionedImagesAdapter(titles, bitmaps, descriptions);
musicRecycler.setAdapter(adapter);
// Set up the layout.
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 1);
musicRecycler.setLayoutManager(layoutManager);
adapter.setListener(new CaptionedImagesAdapter.Listener() {
public void onClick(int position) {
Intent intent;
switch (position) {
case 0:
intent = new Intent(getActivity(), AudioActivity.class);
getActivity().startActivity(intent);
break;
case 1:
intent = new Intent(getActivity(), VideoActivity.class);
getActivity().startActivity(intent);
break;
}
}
});
return musicRecycler;
}
}
Additionally, here is my CaptionedImagesAdapter
class CaptionedImagesAdapter extends
RecyclerView.Adapter<CaptionedImagesAdapter.ViewHolder> {
private final ArrayList<String> captions;
private final ArrayList<Bitmap> bitmaps;
private final ArrayList<String> descriptions;
private Listener listener;
interface Listener {
void onClick(int position);
}
public static class ViewHolder extends RecyclerView.ViewHolder {
private final CardView cardView;
public ViewHolder(CardView v) {
super(v);
cardView = v;
}
}
public CaptionedImagesAdapter(ArrayList<String> captions, ArrayList<Bitmap> bitmaps, ArrayList<String> descriptions) {
this.captions = captions;
this.bitmaps = bitmaps;
this.descriptions = descriptions;
}
#Override
public int getItemCount() {
return captions.size();
}
public void setListener(Listener listener) {
this.listener = listener;
}
#Override
public CaptionedImagesAdapter.ViewHolder onCreateViewHolder(
ViewGroup parent, int viewType) {
CardView cv = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.card_selection_2, parent, false);
return new ViewHolder(cv);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final int index = position;
// Creates a CardView
CardView cardView = holder.cardView;
ImageView imageView = cardView.findViewById(R.id.type_image);
imageView.setImageBitmap(bitmaps.get(index));
imageView.setContentDescription(descriptions.get(index));
// Populate the caption.
TextView textView = cardView.findViewById(R.id.type_text);
textView.setText(captions.get(index));
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v){
if (listener != null)
listener.onClick(index);
}
});
}
}
FOR REFERENCE...... if needed MainActivity.java is below
public class MainActivity extends AppCompatActivity {
// Variables for the audio player.
public static MediaPlayer mediaPlayer;
public static int albumId;
public static int currentSong = -1;
public static boolean isPlaying = false;
private static int[] songs;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar)findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Attach the SectionsPageAdapter to the ViewPager
SectionsPageAdapter pagerAdapter = new SectionsPageAdapter(getSupportFragmentManager());
ViewPager pager = (ViewPager) findViewById(R.id.pager);
pager.setAdapter(pagerAdapter);
int currentTab = 0;
pager.setCurrentItem(currentTab);
// Attach the ViewPager to the TabLayout
TabLayout tabLayout = (TabLayout)findViewById(R.id.tabs);
tabLayout.setupWithViewPager(pager);
// Starts the player.
player();
}
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the app bar.
getMenuInflater().inflate(R.menu.menu_main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch (item.getItemId()) {
case R.id.action_contact:
intent = new Intent(MainActivity.this, ContactActivity.class);
startActivity(intent);
return true;
case R.id.action_cart:
intent = new Intent(this, CartActivity.class);
startActivity(intent);
return true;
case R.id.action_member:
intent = new Intent(this, ProfileActivity.class);
startActivity(intent);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private class SectionsPageAdapter extends FragmentPagerAdapter {
public SectionsPageAdapter(FragmentManager fm) {
super(fm);
}
#Override
public int getCount() {
return 3;
}
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return new MusicFragment();
case 1:
return new ArtFragment();
case 2:
return new FashionFragment();
}
return null;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return getResources().getText(R.string.title_music);
case 1:
return getResources().getText(R.string.title_art);
case 2:
return getResources().getText(R.string.title_fashion);
}
return null;
}
}
private void player() {
/*Create a background thread that will automatically advance to
* the next song, as long as there is a next song.*/
// Get the songs.
songs = AudioData.audio[albumId].getSongs();
final Handler handler = new Handler();
handler.post(new Runnable() {
#Override
public void run() {
if (isPlaying) {
if (!(mediaPlayer.isPlaying()) && currentSong < songs.length - 1) {
mediaPlayer.stop();
mediaPlayer.reset();
currentSong++;
mediaPlayer = MediaPlayer.create(MainActivity.this, songs[currentSong]);
mediaPlayer.start();
isPlaying = true;
}
//Set the flag to false at the end of the album.
if (currentSong == songs.length) {
isPlaying = false;
}
}
handler.postDelayed(this, 1000);
}
});
}
#Override
public void onBackPressed() {
super.onBackPressed();
finishAffinity();
}
}
Thanks again to Harikumar for correcting the first issue. I ended up correcting the second issue with the code below. It was within the enhance for loop.
for (ParseObject object : objects) {
String description = (String) object.get("description");
ParseFile file = (ParseFile) object.get("image");
String title = (String) object.get("title");
Bitmap bitmap;
titles.add(title);
descriptions.add(description);
byte[] data;
try {
data = file.getData();
bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
bitmaps.add(bitmap);
adapter.notifyDataSetChanged(); //notify your adapter that data has changed
} catch (ParseException pe) {
Toast.makeText(getContext(), pe.getMessage(), Toast.LENGTH_SHORT).show();
}
}

Data will be updated if you notify your adapter CaptionedImagesAdapter. Try modifying the code to:
public class MusicFragment extends Fragment {
private ArrayList<String> titles = new ArrayList<>();
private ArrayList<Bitmap> bitmaps = new ArrayList<>();
private ArrayList<String> descriptions = new ArrayList<>();
private CaptionedImagesAdapter adapter;
private boolean notComplete = true;
public MusicFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
RecyclerView musicRecycler = (RecyclerView)inflater.inflate(
R.layout.fragment_music, container, false);
GridLayoutManager layoutManager = new GridLayoutManager(getActivity(), 1);
musicRecycler.setLayoutManager(layoutManager);
adapter = new CaptionedImagesAdapter(titles, bitmaps, descriptions);
musicRecycler.setAdapter(adapter);
if (notComplete) {
// Get the MusicFragImages class as a reference.
ParseQuery<ParseObject> query = new ParseQuery<>("MusicFragImages");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
for (ParseObject object : objects) {
String description = (String) object.get("description");
ParseFile file = (ParseFile) object.get("image");
String title = (String) object.get("title");
titles.add(title);
descriptions.add(description);
file.getDataInBackground(new GetDataCallback() {
#Override
public void done(byte[] data, ParseException e) {
if (e == null && data != null) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
bitmaps.add(bitmap);
adapter.notifyDataSetChanged(); //notify your adapter that data has changed
}
}
});
}
} else {
Toast.makeText(getContext(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
notComplete = false;
}
adapter.setListener(new CaptionedImagesAdapter.Listener() {
public void onClick(int position) {
Intent intent;
switch (position) {
case 0:
intent = new Intent(getActivity(), AudioActivity.class);
getActivity().startActivity(intent);
break;
case 1:
intent = new Intent(getActivity(), VideoActivity.class);
getActivity().startActivity(intent);
break;
}
}
});
return musicRecycler;
}
}
Here is a small optimization for your 2nd solution: update notifyDataSetChanged() only once after the for loop (put it just outside the for loop). This is better in terms of performance.

Related

How to load AdMobs inside RecycleView after every 5th row?

I am trying to implement AdMobs to load ads, every 5th row but i am having a difficult time, as you can see from my screenshot ads are being loaded successfully but they're being loaded after every row. Can someone help me accomplish this? I already tried reading through post on stack overflow but none seems to help. Thank you in advance. image screenshot
Fragment
public class SectorPerformanceFragment extends Fragment {
private RecyclerView newsFeedRecycleView;
private SectorPerformanceAdapter mostActiveAdapter;
private RecyclerViewAdopter recyclerViewAdopter;
public static final int ITEMS_PER_AD = 9;
private RecyclerView.LayoutManager layoutManager;
private RequestQueue requestQueue;
private JSONObject stockDetails;
public static ArrayList<SectorPerformanceModel> mostActiveArrayList;
private RequestQueue requestQueues;
private ImageView backImage;
private View rootView;
private ProgressBar loadingProgressBar;
private TextView sectorNameTv;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.recycle_view_list_ui, container, false);
sectorNameTv = rootView.findViewById(R.id.sectorNameTv);
sectorNameTv.setText("Sector Performance");
loadingProgressBar = rootView.findViewById(R.id.loadingProgressBar);
backImage = rootView.findViewById(R.id.backImageView);
backImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
getActivity().getSupportFragmentManager().popBackStack();
//
// Fragment generalMarketFragment = new BrowseFragment();
// FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
// FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
// fragmentTransaction.replace(R.id.fragment_container, generalMarketFragment);
// fragmentTransaction.addToBackStack(null);
// fragmentTransaction.commit();
}
});
requestQueues = Volley.newRequestQueue(getActivity());
findViewById();
mostActiveArrayList = new ArrayList<>();
initRecycleView();
retreiveBundleInformation();
return rootView;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
private void findViewById() {
newsFeedRecycleView = rootView.findViewById(R.id.recylcle_view_list);
}
//set up RecycleVIew/listener to detect taps layout manager tels recycle view how to display the list.. without it, nothing shows up
public void initRecycleView() {
layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
newsFeedRecycleView.setHasFixedSize(true);
newsFeedRecycleView.setLayoutManager(layoutManager);
//mostActiveAdapter = new SectorPerformanceAdapter(getContext(), mostActiveArrayList);
// recyclerViewAdopter = new RecyclerViewAdopter(getContext(),mostActiveArrayList);
//
// //newsFeedRecycleView.setAdapter(mostActiveAdapter);
// newsFeedRecycleView.setAdapter(recyclerViewAdopter);
}
//download news data stocknewsapi..
private void downloadStockList(String api) {
// Initialize a new JsonArrayRequest instance
JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(
Request.Method.GET,
api,
null,
new Response.Listener<JSONArray>() {
#Override
public void onResponse(JSONArray response) {
// Do something with response
//mTextView.setText(response.toString());
loadingProgressBar.setVisibility(View.INVISIBLE);
//Log.i("jsonResponse", response.toString());
// Process the JSON
// Loop through the array elements
for (int i = 0; i < response.length(); i++) {
// Get current json object
try {
stockDetails = response.getJSONObject(i);
Log.i("stockDetails", stockDetails.toString());
SectorPerformanceModel sectorPerformanceModel2 = new SectorPerformanceModel(stockDetails.getString("sector"),stockDetails.getString("changesPercentage"),1);
mostActiveArrayList.add((sectorPerformanceModel2));
SectorPerformanceModel sectorPerformanceModel3 = new SectorPerformanceModel(stockDetails.getString("sector"),stockDetails.getString("changesPercentage"),2);
mostActiveArrayList.add(mostActiveArrayList.size(),sectorPerformanceModel3);
recyclerViewAdopter = new RecyclerViewAdopter(getContext(),mostActiveArrayList);
//newsFeedRecycleView.setAdapter(mostActiveAdapter);
newsFeedRecycleView.setAdapter(recyclerViewAdopter);
//recyclerViewAdopter.notifyDataSetChanged();
// mostActiveArrayList.add(sectorPerformanceModel);
// mostActiveAdapter.notifyDataSetChanged();
} catch (JSONException e) {
e.printStackTrace();
}
}
}
},
new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.i("error", error.toString());
}
}
);
// Add JsonArrayRequest to the RequestQueue
requestQueues.add(jsonArrayRequest);
}
public void retreiveBundleInformation() {
downloadStockList("APIKEY");
}
}
Adapter
[public class RecyclerViewAdopter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private Context mContext;
private List<SectorPerformanceModel> mList;
public RecyclerViewAdopter(Context mContext, List<SectorPerformanceModel> mList) {
this.mList = mList;
this.mContext = mContext;
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
private TextView newsTitle, sourceName, epsEstiatmate;
private CircleImageView newsThumbImage;
public MyViewHolder(View view) {
super(view);
epsEstiatmate = itemView.findViewById(R.id.formTypeTv);
newsTitle = itemView.findViewById(R.id.tickerTv);
sourceName = itemView.findViewById(R.id.dateTv);
newsThumbImage= itemView.findViewById(R.id.defaultImageColor);
newsThumbImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i("tapped","TAPPED");
}
});
}
}
public static class ViewHolderAdMob extends RecyclerView.ViewHolder {
public AdView mAdView;
public ViewHolderAdMob(View view) {
super(view);
mAdView = (AdView) view.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice(AdRequest.DEVICE_ID_EMULATOR)
.build();
mAdView.loadAd(adRequest);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch(viewType){
case 1:{
View v = inflater.inflate(R.layout.trending_stock_row, parent, false);
viewHolder = new MyViewHolder(v);
break;
}
case 2:{
View v = inflater.inflate(R.layout.ads_row, parent, false);
viewHolder = new ViewHolderAdMob(v);
break;
}
}
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
SectorPerformanceModel model= mList.get(holder.getAdapterPosition());
switch(holder.getItemViewType()){
case 1:{
MyViewHolder viewHolder = (MyViewHolder) holder;
Random r = new Random();
int red = r.nextInt(255 - 0 + 1) + 0;
int green = r.nextInt(255 - 0 + 1) + 0;
int blue = r.nextInt(255 - 0 + 1) + 0;
GradientDrawable draw = new GradientDrawable();
draw.setShape(GradientDrawable.OVAL);
draw.setColor(Color.rgb(red, green, blue));
viewHolder.newsThumbImage.setBackground(draw);
viewHolder.newsTitle.setText(model.getSector());
viewHolder.sourceName.setText(model.getChangesPercentage());
break;
}
case 2:{
break;
}
}
}
#Override
public int getItemViewType(int position) {
return mList.get(position).getViewType();
}
#Override
public int getItemCount() {
return mList.size();
}
}][1]
It looks like you are adding 2 items to your adapter's data source for each element in your API response: one element has viewType 1 and the other viewType 2:
SectorPerformanceModel sectorPerformanceModel2 = new SectorPerformanceModel(stockDetails.getString("sector"),stockDetails.getString("changesPercentage"),1);
mostActiveArrayList.add((sectorPerformanceModel2));
SectorPerformanceModel sectorPerformanceModel3 = new SectorPerformanceModel(stockDetails.getString("sector"),stockDetails.getString("changesPercentage"),2);
mostActiveArrayList.add(mostActiveArrayList.size(),sectorPerformanceModel3);
Your adapter is rendering items with viewType 2 as ad rows, so if you want to display an ad row every 5 rows you'll need to update the downloadStockList method to execute this
SectorPerformanceModel sectorPerformanceModel3 = new SectorPerformanceModel(stockDetails.getString("sector"),stockDetails.getString("changesPercentage"),2);
mostActiveArrayList.add(mostActiveArrayList.size(),sectorPerformanceModel3);
only after having added 4 items with viewType 1.

get context after returning from adapter to fragment

I am using contextual action bar in my fragment("UnitsFragment.java") to delete and edit items of recyclerview. But when I come back from recyclerview adapter class("UnitsRv.java"). The context seems to be null. I tried returning context from adapter and it worked for function "prepareSelection". However for "onActionItemClicked" under ActionMode.callback, I need to get context so that I can use alertdialog for editing the items.
The "requireContext()" throws this error: Fragment UnitsFragment{e3a36c8 (b4957397-055a-4b1c-8af2-fee89a3e9b35)} not attached to a context.
Here are my codes.
UnitsFragment.java
public class UnitsFragment extends Fragment {
private static final String TAG = "UnitsFragment";
private RecyclerView recyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager layoutManager;
ArrayList<UnitsList> unitsLists = new ArrayList<>();
Activity mcontext = getActivity();
Context dcontext;
ActionMode actionMode;
public static ArrayList<UnitsList> selectionList = new ArrayList<>();
public static boolean isInActionMode = false;
List<String> list = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao().findUnitNameList();
public UnitsFragment() {
}
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_item_action, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_edit:
if (selectionList.size() == 1) {
final EditText editText = new EditText(requireContext());
new AlertDialog.Builder(requireContext())
.setTitle("Rename unit name").setView(editText)
.setPositiveButton("Rename", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
UnitsList unitsList = selectionList.get(0);
unitsList.setUnit_name(editText.getText().toString().trim());
isInActionMode = false;
((UnitsRv) mAdapter).changeDataItem(getCheckedLastPosition(), unitsList);
actionMode.finish();
selectionList.clear();
}
})
.create()
.show();
Toast.makeText(getContext(), "Edit", Toast.LENGTH_SHORT).show();
mode.finish();
return true;
}
case R.id.menu_item_delete:
isInActionMode = false;
((UnitsRv) mAdapter).removeData(selectionList);
Toast.makeText(getContext(), "Delete", Toast.LENGTH_SHORT).show();
actionMode.finish();
selectionList.clear();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
actionMode = null;
}
};
private int getCheckedLastPosition() {
ArrayList<UnitsList> dataSet = UnitsRv.getDataSet();
for (int i = 0; i < dataSet.size(); i++) {
if (dataSet.get(i).equals(selectionList.get(0))) {
return i;
}
}
return 0;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
dcontext = rootView.getContext();
Log.d(TAG, "onCreateView1: " + dcontext);
recyclerView = rootView.findViewById(R.id.rv_units);
recyclerView.setHasFixedSize(true);
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.HORIZONTAL));
recyclerView.addItemDecoration(new DividerItemDecoration(getContext(),
DividerItemDecoration.VERTICAL));
layoutManager = new GridLayoutManager(getContext(), 2);
recyclerView.setLayoutManager(layoutManager);
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
Log.d(TAG, "onCreateView: " + getContext());
mAdapter = new UnitsRv(mcontext,unitsLists);
recyclerView.setAdapter(mAdapter);
return rootView;
}
#Override
public void onCreateOptionsMenu(#NonNull Menu menu, #NonNull MenuInflater inflater) {
inflater.inflate(R.menu.add, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_new:
final View customLayout = getLayoutInflater().inflate(R.layout.add_unit_dialog, null);
final EditText edt_unit_name = customLayout.findViewById(R.id.edt_new_unit_name);
final AlertDialog dialog = new AlertDialog.Builder(getContext())
.setView(customLayout)
.setTitle("Unit name")
.setPositiveButton(android.R.string.ok, null) //Set to null. We override the onclick
.setNegativeButton(android.R.string.cancel, null)
.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialogInterface) {
Button ok_btn = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button cancel_btn = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
ok_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String unit_name = edt_unit_name.getText().toString().trim();
if (!TextUtils.isEmpty(unit_name)) {
String old_unit_name = DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.findByUnitName(unit_name);
if (old_unit_name == null) {
DatabaseClient.getInstance(getContext())
.getUserDatabase()
.getUnitDao()
.insertUnits(new UnitsList(unit_name));
unitsLists.add(new UnitsList(unit_name));
dialog.dismiss();
} else {
edt_unit_name.setError("Unit already exists");
}
} else {
edt_unit_name.setError("Can't be empty");
}
}
});
cancel_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
dialog.dismiss();
}
});
}
});
dialog.show();
return true;
}
return super.onOptionsItemSelected(item);
}
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists);
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
private void updateViewCounter() {
int counter = selectionList.size();
if (counter == 1) {
actionMode.setTitle(counter + "item selected");
} else {
actionMode.setTitle(counter + "items selected");
}
}
}
This is my Adapter class.
UnitsRv.java
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment();
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists) {
mcontext = context;
munitsLists = unitsLists;
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
unitsFragment.prepareSelection(mcontext,getAdapterPosition());
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
unitsFragment.prepareSelection(view.getContext(),getAdapterPosition());
return true;
}
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.units_item, parent, false);
return new ViewHolder(itemView);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder holder, final int position) {
holder.unit_name.setText(munitsLists.get(position).getUnit_name());
if (UnitsFragment.isInActionMode){
if (UnitsFragment.selectionList.contains(munitsLists.get(position))){
holder.itemView.setBackgroundResource(R.color.colorSelected);
}
}
}
#Override
public int getItemCount() {
return munitsLists.size();
}
public static ArrayList<UnitsList> getDataSet() {
return munitsLists;
}
public void changeDataItem(int position, UnitsList unitsList) {
munitsLists.set(position, unitsList);
notifyDataSetChanged();
}
public void removeData(ArrayList<UnitsList> list) {
for (UnitsList unitsList : list) {
munitsLists.remove(unitsList);
}
notifyDataSetChanged();
}
}
First, you should not create instance of your UnitsFragment inside your adapter.
You can use EventBus to communicate between Activities, Fragments, Adapters, etc.
Or You can do your task using interface. like below.
Create an interface like this
public interface AdapterCallback {
void prepareSelection(Context context,int position);
}
In your UnitsFragment implement the above interface. like the following
public class UnitsFragment extends Fragment implements AdapterCallback{
// your other codes
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_units, container, false);
setHasOptionsMenu(true);
// .... your other codes
Log.d(TAG, "onCreateView: " + getContext());
// modify below line like this
mAdapter = new UnitsRv(mcontext, unitsLists, this); // here you have to pass an extra parameter that will implement your callback method from adapter.
recyclerView.setAdapter(mAdapter);
return rootView;
}
// ... you other codes
#Override
public void prepareSelection(Context context,int position) {
if(actionMode == null) {
isInActionMode = true;
for (String string : list) {
unitsLists.add(new UnitsList(string));
}
mAdapter = new UnitsRv(context, unitsLists,this); // add this as parameter.
Log.d(TAG, "prepareSelection: " + mAdapter);
Log.d(TAG, "prepareSelection1: " + dcontext);
mcontext = (Activity)context;
actionMode = mcontext.startActionMode(actionModeCallback);
mAdapter.notifyDataSetChanged();
if (!selectionList.contains(unitsLists.get(position))) {
selectionList.add(unitsLists.get(position));
}
updateViewCounter();
}
}
// other codes
}
Now, inside your Adapter you need to add an extra argument in constructor of UnitsRv and call your interface method from adapter ussing mAdapterCallback.
public class UnitsRv extends RecyclerView.Adapter<UnitsRv.ViewHolder> {
private static final String TAG = "UnitsRv";
private static ArrayList<UnitsList> munitsLists = new ArrayList<>();
UnitsFragment unitsFragment = new UnitsFragment(); // remove this line
private AdapterCallback mAdapterCallback; // add this line
Context mcontext;
public UnitsRv(Context context,ArrayList<UnitsList> unitsLists, AdapterCallback callback) {
mcontext = context;
munitsLists = unitsLists;
this.mAdapterCallback = callback; // add this line
}
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView unit_name;
public ViewHolder(View v) {
super(v);
unit_name = v.findViewById(R.id.unit_name);
v.setOnLongClickListener(this);
}
#Override
public void onClick(View view) {
if (UnitsFragment.isInActionMode){
mAdapterCallback.prepareSelection(mcontext,getAdapterPosition()); // modify this line
notifyItemChanged(getAdapterPosition());
}
}
#Override
public boolean onLongClick(View view) {
Log.d(TAG, "onLongClick: " + getAdapterPosition());
mAdapterCallback.prepareSelection(view.getContext(),getAdapterPosition()); // modify this line
return true;
}
}
// your other codes....
}
You should check for your fragment is attached or not with isAdded()
place if(!isAdded()) return in your onActionItemClicked. and replace requireContext() with getContext() because requireContext() always throws IllegalStateException if fragment is not attached.
override onAttach method to save context in your fragment.
#Override
public void onAttach(Context context) {
super.onAttach(context);
this.context= context;
}
Hope this helps.

how to save ArrayLists Position at orientation change

I'm currently facing a bug in restoring the Position of an ArrayList after orientation cchange to enhance the user experience. I try to store the ArrayList and already made movieData Parcelable. When using a debugger after orientation change savedInstance obviously is not null and contained an int value and presumably the parcelable Array List and I don't really know why this code doesn't work yet.
Fragment Class:
public class MovieGridFragment extends Fragment {
public clickInterfaceHelper clickListener;
private GridView movieGridView;
private int index;
public List<movieData> movieDataList = new ArrayList<>();
public ArrayList<movieData> restoreList;
public MovieGridFragment() {} //empty constructor
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
public void setClickListener(clickInterfaceHelper listener) {
this.clickListener = listener;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState != null)
index = savedInstanceState.getInt("INDEX");
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
setHasOptionsMenu(true);
if(movieDataList.isEmpty() && networkChecker.isNetworkAvailableChecker(getContext())) {
movieDataList = new ArrayList<movieData>();
}
if(!movieDataList.isEmpty() && !networkChecker.isNetworkAvailableChecker(getContext())) {
movieDataList = new ArrayList<movieData>();
}
View rootView = inflater.inflate(R.layout.movie_display_fragment, container, false);
movieGridView = (GridView) rootView.findViewById(R.id.gv_movie_display);
if(savedInstanceState != null && savedInstanceState.containsKey("OLDMOVIEDATA")) {
//index = savedInstanceState.getInt("INDEX");
//movieDataList.addAll(Arrays.asList((movieData[]) savedInstanceState.getSerializable("OLDMOVIEDATA")));
restoreList = savedInstanceState.getParcelableArrayList("OLDMOVIEDATA");
movieAdapter adapter = new movieAdapter(getActivity(),restoreList);
adapter.notifyDataSetChanged();
//movieGridView.setAdapter(adapter);
movieGridView.smoothScrollToPosition(index);
}
else {
movieAdapter adapter = new movieAdapter(getActivity(), movieDataList);
adapter.notifyDataSetChanged();
movieGridView.setAdapter(adapter);
}
movieGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(clickListener != null)
clickListener.clickOnItem(position);
}
});
return rootView;
}
#Override
public void onSaveInstanceState(Bundle outState) {
//outState.putSerializable("OLDMOVIEDATA",movieData.movieDataArray);
outState.putParcelableArrayList("OLDMOVIEDATA",restoreList);
outState.putInt("INDEX",movieGridView.getFirstVisiblePosition());
super.onSaveInstanceState(outState);
}
}
Adapter:
public class movieAdapter extends ArrayAdapter<movieData> {
public movieAdapter(Context context, List<movieData> movieObject) {
super(context, 0, movieObject);
}
public View getView(int pos, View convertingView, ViewGroup viewGroup) {
movieData movieDatas = getItem(pos);
String url="http://image.tmdb.org/t/p/w185"+movieDatas.getMovieImagePath();
if(convertingView == null)
convertingView = LayoutInflater.from(getContext()).inflate(R.layout.image_display,viewGroup,false);
ImageView imageView = (ImageView) convertingView.findViewById(R.id.iv_movie_image);
Picasso.with(getContext()).load(url.trim()).into(imageView);
return convertingView;
}
}
and the main activity:
public class MainActivity extends AppCompatActivity implements clickInterfaceHelper {
public static String sorterString = null;
public static String urlBase = "https://api.themoviedb.org/3/movie/";
public static String urlFinal = null;
RequestQueue requestQueue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(savedInstanceState == null) {
MovieGridFragment fragment = new MovieGridFragment();
fragment.setClickListener(this);
getSupportFragmentManager().beginTransaction()
.add(R.id.activity_container, fragment)
.commit();
movieData.movieDataPosition = 0;
}
if(savedInstanceState != null) {
sorterString = savedInstanceState.getString("SORTER");
}
if(sorterString==null)
sorterString="popular?";
if(sorterString!="favorite" && sorterString!=null) {
if(networkChecker.isNetworkAvailableChecker(this)) {
movieRequest();
}
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu_act, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if(id == R.id.m_popularity_action) {
if(sorterString != "popular?") {
sorterString = "popular?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_action_voter) {
if(sorterString != "top_rated?") {
sorterString = "top_rated?";
if(networkChecker.isNetworkAvailableChecker(this))
movieRequest();
}
return true;
}
if(id == R.id.m_favorite_btn) {
if(sorterString != "favorite") {
SQLiteOpenHelper helper = new movieDataDbHelper(this);
SQLiteDatabase database = helper.getReadableDatabase();
Cursor cursor= database.query(movieDataContract.contractEntry.TABLE_NAME,
new String[] {
movieDataContract.contractEntry.ID,
movieDataContract.contractEntry.IMG_PATH},null,null,null,null,null);
if(cursor.getCount() == 0) {
Toast.makeText(this, "there are no favorite movies yet!",Toast.LENGTH_SHORT).show();
} else {
sorterString = "favorite";
showFavoriteFragment();
}
database.close();
helper.close();
cursor.close();
}
return true;
}
return super.onOptionsItemSelected(item);
}
public void showFavoriteFragment() {
favoriteMoviesDetailsFragment fragment = new favoriteMoviesDetailsFragment();
try {
getFragmentManager().beginTransaction().replace(R.id.activity_container,fragment).commit();
} catch (Exception e) {
e.printStackTrace();
}
}
#Override
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
outState.putString("SORTER", sorterString);
outState.putInt("POSITION",movieData.movieDataPosition);
super.onSaveInstanceState(outState, outPersistentState);
}
public void movieRequest() {
final MovieGridFragment gridFragment = new MovieGridFragment();
gridFragment.setClickListener(this);
urlFinal = urlBase + sorterString + movieData.apiKey;
urlFinal.trim();
requestQueue = Volley.newRequestQueue(this);
JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.GET, urlFinal, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray array = response.getJSONArray("results");
movieData.movieDataArray = new movieData[array.length()];
for (int i = 0; i < array.length(); i++) {
movieData movie = new movieData();
JSONObject jsonObject = array.getJSONObject(i);
movie.setMovieId(jsonObject.getString("id"));
movie.setMovieImagePath(jsonObject.getString("poster_path"));
movie.setMovieTitle(jsonObject.getString("original_title"));
movie.setMoviePlot(jsonObject.getString("overview"));
movie.setMovieVoting(jsonObject.getString("vote_average"));
movie.setMovieReleaseDate(jsonObject.getString("release_date"));
movieData.movieDataArray[i] = movie;
}
gridFragment.movieDataList = Arrays.asList(movieData.movieDataArray);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.activity_container, gridFragment);
try {
transaction.commitAllowingStateLoss();
} catch (Exception e) {
e.printStackTrace();
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("volley", String.valueOf(error));
}
}
);
requestQueue.add(jsonObjectRequest);
}
#Override
public void clickOnItem(int id) {
movieData.movieDataPosition = id;
if(movieData.movieDataArray == null) {
movieRequest();
} else {
Intent intent = new Intent(this, detailsActivity.class);
intent.putExtra("FRAGMENT","MOVIE");
startActivity(intent);
}
}
#Override
public void favoriteMovieItem(int movieId) {
movieData.dbPosition = movieId;
Intent intent = new Intent(this,detailsActivity.class);
intent.putExtra("FRAGMENT","favorite");
startActivity(intent);
}
}
You already use the
#Override
public void onSaveInstanceState(Bundle outState) {
//outState.putSerializable("OLDMOVIEDATA",movieData.movieDataArray);
outState.putParcelableArrayList("OLDMOVIEDATA",restoreList);
outState.putInt("INDEX",movieGridView.getFirstVisiblePosition());
super.onSaveInstanceState(outState);
}
Just use it to store the position you need to save. Get the position back using the bundle given in the "onCreateView".
If it does not work, put "setRetainInstance(true)" in the "onCreate" function of your fragment. It will prevent your fragment being destroyed then recreated from nothing during orientation change.
However, I read somewhere that's not the correct way to do so with fragment having UI elements (but i never found anything wrong doing this).
If you want an alternative way not using "setRetainInstance", store (and restore) the position on the activity
public void onSaveInstanceState(Bundle outState)"
function. To do so, create a function "getPosition()" in your fragment, call it in the activity saveInstanceState, and create a function "refresh(int position)" in your fragment (and call it on the restored position value) once the fragment is loaded/recreated in the activity.

How to change Tabs of a TabLayout from Navigation Drawer

Currently I'm changing Tabs from NavigationDrawer but it's not a right way and it takes too long to change tabs from NavigationDrawer becuase I'm replacing Main Fragment of Tabs each time and I don't want it. For more
NavigationDrawerAdapter.java
public class NavDrawerListAdapter extends BaseAdapter {
public Context context;
public MainActivity activity;
public MainTabFragment fragment;
int currentSelectedPostion;
LayoutInflater mInflater;
TextView tv_signup;
SharedPreferences share;
boolean cbc = false;
String fis = "", las = "";
int group_id = 0;
private String[] titles;
private int[] images;
private int[] selectedposition;
public NavDrawerListAdapter(Context context, int[] selectedposition, boolean cb, String fis, String las) {
this.context = context;
this.images = images;
this.cbc = cb;
this.fis = fis;
this.las = las;
share = context.getSharedPreferences("sharePref", 0);
group_id = share.getInt("group_id", 0);
this.selectedposition = selectedposition;
mInflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
return 1;
}
#Override
public Object getItem(int position) {
return position;
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = mInflater.inflate(com.cws.advisorymandi.R.layout.drawer_list_item, null);
}
LinearLayout ll_contact_us = (LinearLayout) convertView.findViewById(com.cws.advisorymandi.R.id.contact_item);
RelativeLayout ll_login = (RelativeLayout) convertView.findViewById(com.cws.advisorymandi.R.id.signup_item);
LinearLayout ll_equity = (LinearLayout) convertView.findViewById(com.cws.advisorymandi.R.id.equity_item);
LinearLayout ll_indices = (LinearLayout) convertView.findViewById(com.cws.advisorymandi.R.id.indices_item);
if (cbc) {
tv_signup.setText("Welcome " + fis + " " + las);
tv_logout.setVisibility(View.VISIBLE);
tv_edit.setVisibility(View.VISIBLE);
}
ll_equity.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.getInstance().displayView(3, 0, 0);
}
});
ll_indices.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
MainActivity.getInstance().displayView(3, 0, 1);
}
});
});
return convertView;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
public ListView mDrawerList;
NavDrawerListAdapter adapter;
public static MainActivity getInstance() {
return sMainActivity;
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(com.cws.advisorymandi.R.layout.activity_main)
mDrawerList = (ListView) findViewById(com.cws.advisorymandi.R.id.list_slidermenu);
adapter = new NavDrawerListAdapter(getApplicationContext(), selectedposition, cb, firstName, lastName);
mDrawerList.setAdapter(adapter);
}
/**
* Diplaying fragment view for selected nav drawer list item
*/
public int displayView(int position, int position2, int position3) {
// update the main content by replacing fragments
first_position = position;
second_position = position2;
third_position = position3;
fragment = null;
switch (position) {
case 0:
sharedPreferences = getSharedPreferences("sharePref", 0);
cb = sharedPreferences.getBoolean("ConfirmLogin", false);
if (cb) {
} else new Handler().postDelayed(new Runnable() {
#Override
public void run() {
fragment = new LoginActivity();
changeFragments3();
}
}, 150);
mDrawerLayout.closeDrawer(mDrawerList);
break;
case 3:
// fragment = new MainTabFragment();
/* new Handler().postDelayed(new Runnable() {
#Override
public void run() {*/
fragment = new MainTabFragment();
changeFragments();
/*}
}, 150);
mDrawerLayout.closeDrawer(mDrawerList);*/
break;
}
return 0;
}
}
Note: I created each drawer item without using an array or arrayList so onItemClickListener isn't also working in it.

invalidateViews() and notifyDataSetChanged() doesnt work for me

i using ListView in fragment. I have one asynctask to download json data from remote server. I try refresh programmatically my displayed adapter/listview in onPostExecute function but it doesn't work for me.
My main activity with three fragments, three listview, three adapter and one async task.
public class ContactsActivity extends ActionBarActivity implements ActionBar.TabListener {
SectionsPagerAdapter mSectionsPagerAdapter;
ViewPager mViewPager;
private static List<Item> BackList = new ArrayList<Item>();
private static List<Item> BackList2 = new ArrayList<Item>();
private static List<Item> BackList3 = new ArrayList<Item>();
private static ListView ListView;
private static Context activity;
public static String HASH;
private static final String[] timestamp = {"0"};
private static WeatherAdapter adapter;
private static int fragment;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contacts);
Intent myIntent= getIntent();
HASH = myIntent.getStringExtra("HASH");
Log.d("Intent - contactActivity", HASH);
final ActionBar actionBar = getSupportActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.pager);
mViewPager.setAdapter(mSectionsPagerAdapter);
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
});
for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {
actionBar.addTab(
actionBar.newTab()
.setText(mSectionsPagerAdapter.getPageTitle(i))
.setTabListener(this));
}
(new PrefetchData()).execute();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.contacts, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
mViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
#Override
public void onTabReselected(ActionBar.Tab tab, FragmentTransaction fragmentTransaction) {
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
return PlaceholderFragment.newInstance(position + 1);
}
#Override
public int getCount() {
return 3;
}
#Override
public CharSequence getPageTitle(int position) {
Locale l = Locale.getDefault();
fragment = position;
switch (position) {
case 0:
return getString(R.string.title_section1).toUpperCase(l);
case 1:
return getString(R.string.title_section2).toUpperCase(l);
case 2:
return getString(R.string.title_section3).toUpperCase(l);
}
return null;
}
}
public static Bitmap getBitmapFromURL(String src) {
try {
URL url = new URL(src);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap myBitmap = BitmapFactory.decodeStream(input);
return myBitmap;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
public PlaceholderFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
int index = getArguments().getInt(ARG_SECTION_NUMBER);
fragment = index;
activity = getActivity();
ListView listview1 = (ListView) rootView.findViewById(R.id.listView);
switch(fragment){
case 1:
adapter = new WeatherAdapter(activity, R.layout.listview_item_row, BackList);
listview1.setOnItemClickListener(new ListView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> a, View v, int i, long l) {
Intent rozmowa = new Intent(getActivity(), Incotalk.class);
rozmowa.putExtra("HASH", HASH);
startActivity(rozmowa);
}
});
break;
case 2:
adapter = new WeatherAdapter(activity, R.layout.listview_item_row2, BackList2);
break;
case 3:
adapter = new WeatherAdapter(activity, R.layout.listview_item_row3, BackList3);
break;
}
listview1.setAdapter(adapter);
ListView = listview1;
return rootView;
}
}
/**
* Async Task to make http call
*/
private class PrefetchData extends AsyncTask<Void, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// before making http calls
}
#Override
protected Void doInBackground(Void... arg0) {
final String id = HASH;
final String url = "http://freshfrog.pl/projects/talk.php?user="+id+"&t=" + timestamp[0];
Log.d("BBB","start");
try {
String page = new Communicator().executeHttpGet(url);
JSONObject jsonObject = new JSONObject(page);
timestamp[0] = jsonObject.getString("t");
HASH = jsonObject.getJSONObject("s").getString("hash");
JSONArray oczekujacy = jsonObject.getJSONArray("m");
// wiadomosci
BackList.clear(); // czyści przed odświerzeniem
BackList2.clear();
BackList3.clear();
for (int i=oczekujacy.length()-1; i>0; i--) {
JSONObject actor = oczekujacy.getJSONObject(i);
String message = actor.getString("m");
String hash = actor.getString("n");
String t = actor.getString("t");
int l = BackList.size();
Boolean jest = false;
for(int j=0; j<l; j++){
Item item = BackList.get(j);
if(!item.isSection()){
ContactItem contactItem= (ContactItem) item;
if( (contactItem.hash).equals(hash) ){
jest = true;
break;
}
}
//Log.d("bbb", BackList.get(j).hash);
}
if(!jest && !hash.equals(id)) BackList.add(
new ContactItem(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher),
message,
hash));
}
// znajomi
BackList2.add(new SectionItem("Otrzymane zaproszenia"));
oczekujacy = jsonObject.getJSONObject("f").getJSONObject("p").getJSONArray("sending");
for (int i=0; i<oczekujacy.length(); i++) {
JSONObject actor = oczekujacy.getJSONObject(i);
String name = actor.getString("name");
String hash = actor.getString("hash");
String avatar = actor.getString("avatar");
BackList2.add(new ContactItem(getBitmapFromURL(avatar) , name, hash) );
}
// szukaj
BackList3.add(new SectionItem("Znajomi"));
Cursor phones = getContentResolver().query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,null,null, null);
while (phones.moveToNext())
{
String name= phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String phoneNumber = phones.getString(phones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
BackList3.add(new ContactItem(
BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher),
name,
phoneNumber) );
}
} catch (Exception e) {
Log.d("BBB", e.toString());
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
/* gdy skończy */
adapter.notifyDataSetChanged();
ListView listview2 = (ListView) findViewById(R.id.listView);
listview2.invalidateViews();
//Toast.makeText(ContactsActivity.this, "coś przyszło", Toast.LENGTH_SHORT).show();
Log.d("BBB", "powinno sie odswieżyc");
new PrefetchData().execute();
}
}
}
My custom adapter
public class WeatherAdapter extends ArrayAdapter<Item> {
Context context;
int layoutResourceId;
List<Item> data = null;
private LayoutInflater vi;
public WeatherAdapter(Context context, int layoutResourceId, List<Item> data) {
super(context, layoutResourceId, data);
this.layoutResourceId = layoutResourceId;
this.context = context;
this.data = data;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = convertView;
WeatherHolder holder = null;
SectionHolder holder2 = null;
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
Item i = data.get(position);
if(row == null){
if(!i.isSection()){
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder);
ContactItem contactItem = (ContactItem)i;
holder.txtTitle.setText(contactItem.title);
holder.imgIcon.setImageBitmap(contactItem.icon);
}else{
row = inflater.inflate(R.layout.listview_header_row, parent, false);
holder2 = new SectionHolder();
holder2.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder2);
SectionItem sectionItem = (SectionItem)i;
holder2.txtTitle.setText(sectionItem.title);
}
}
else
{
if(!i.isSection()){
//holder = (WeatherHolder) row.getTag();
}else{
//holder2 = (SectionHolder) row.getTag();
}
}
return row;
}
public void update(List<Item> newlist) {
Log.d("bbb","aktualizacja listview");
data.clear();
data.addAll(newlist);
this.notifyDataSetChanged();
}
#Override
public void notifyDataSetChanged() // Create this function in your adapter class
{
//notifySetDataChanged()
super.notifyDataSetChanged();
}
static class WeatherHolder
{
ImageView imgIcon;
TextView txtTitle;
}
static class SectionHolder
{
TextView txtTitle;
}
}
the part of the "if(row == null){" should only contain initializations of the views and the viewHolders.
it shouldn't contain any setting of data to the views.
after this part ( after the "else {...}" ) , you should update the views with the new data .
here's my fix to your code (looks ugly, but should work) :
...
int type=getViewType();
switch(type)
{
case 0:
if(row == null)
{
row = inflater.inflate(layoutResourceId, parent, false);
holder = new WeatherHolder();
holder.imgIcon = (ImageView)row.findViewById(R.id.imgIcon);
holder.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder);
}
else
holder = (WeatherHolder) row.getTag();
ContactItem contactItem = (ContactItem)i;
holder.txtTitle.setText(contactItem.title);
holder.imgIcon.setImageBitmap(contactItem.icon);
break;
case 1:
if(row == null)
{
row = inflater.inflate(R.layout.listview_header_row, parent, false);
holder2 = new SectionHolder();
holder2.txtTitle = (TextView)row.findViewById(R.id.txtTitle);
row.setTag(holder2);
}
else
holder2 = (SectionHolder) row.getTag();
SectionItem sectionItem = (SectionItem)i;
holder2.txtTitle.setText(sectionItem.title);
break;
}
return row;
...
... int getViewType(...) {... return i.isSection()? 1:0;}
... int getViewTypeCount(){return 2;}
btw, you should really watch the lecture "the world of listView" . they have great tips that will make your code much better.
for example, you can use getViewTypeCount , getViewType, getItem, as shown on the API .
to view your code i see that you have started your async execution again on postExcecute
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
/* gdy skończy */
adapter.notifyDataSetChanged();
ListView listview2 = (ListView) findViewById(R.id.listView);
listview2.invalidateViews();
//Toast.makeText(ContactsActivity.this, "coś przyszło", Toast.LENGTH_SHORT).show();
Log.d("BBB", "powinno sie odswieżyc");
new PrefetchData().execute();
}
also clearing data inside your doBackground
To get changes on your data you should not clear your data just get updates records and notify your adapeter
try to change the method data.addAll(newlist) by using addall(newlist, data);
inside addall method add one by one the list of element. this way it should work.
i had the same problem and i correct it the way i explained.

Categories

Resources