Why is my android.R.id.home not called in my fragment? - java

I'm currently using FragmentStatePagerAdapter and I would like it to have a "navigate up" feature (DisplayHomeAsUpEnabled). When I set the following code it shows up as a correct navigate back button. But nothing happens when I click on it, can you guys see anything that I', doing wrong in my code, I get no error while pressing the "navigate up" button and I get no compiler errors.
Here is the code, its in the "public boolean onOptionsItemSelected(MenuItem item) {" it gets interesting at the bottom.
public class ShareholdingDetailFragment extends FragmentActivity {
final int NUM_ITEMS = Portfolio.getPortfolio().count();
MyAdapter mAdapter;
ViewPager mPager;
Bundle extras;
#Override
protected void onCreate(Bundle savedInstanceState) {
System.out.println(NUM_ITEMS + "e");
super.onCreate(savedInstanceState);
setContentView(R.layout.shareholdingdetailview_fragment_wrapper);
mAdapter = new MyAdapter(getSupportFragmentManager());
mPager = (ViewPager)findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
}
public class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
public int getCount() {
return NUM_ITEMS;
}
public Fragment getItem(int position) {
return ShareholdingFragment.newInstance(position);
}
}
public static class ShareholdingFragment extends Fragment {
int mNum;
static ShareholdingFragment newInstance(int num) {
ShareholdingFragment f = new ShareholdingFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
}
#SuppressLint({ "NewApi", "NewApi" })
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.shareholdingdetailview_fragment, container, false);
/****************Setting the Display as home and it shows*******************/
ActionBar bar = getActivity().getActionBar();
bar.setDisplayHomeAsUpEnabled(true);
/**********************************/
return view;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home://Not working
System.out.println("test");//This isn't printed out
Intent upIntent = new Intent(getActivity(), DetailShareHoldingActivity.class);
if (NavUtils.shouldUpRecreateTask(getActivity(), upIntent)) {
getActivity().finish();
} else {
NavUtils.navigateUpTo(getActivity(), upIntent);
}
return true;
}
return super.onOptionsItemSelected(item);
}
}
}

Try adding: setHasOptionsMenu(true); in your onCreate() in ShareholdingFragment.

Add setHomeButtonEnabled(true) on API Level 14 and higher when you configure your action bar. On API Level 11-13, the home button is enabled automatically.

If you're using the new Toolbar and ActionbarDrawerToggle. You can assign clickHandler directly. For my activities that have this drawer toolbar I implemented an interface to enable drawer if at root,
#Override
public void enableDrawer(boolean enable) {
mDrawerToggle.setDrawerIndicatorEnabled(enable);
mDrawerToggle.setToolbarNavigationClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Pop fragment back stack or pass in a custom click handler from the fragment.
}
});
}

Related

How do I use back stack or get getChildFragmentManager() with this specific pager adapter in order to use the back button?

I'm using Fragments to change scenes in my application, and I've come across the problem where when the phone back button is pressed, the application closes. How would I make it so when the back button is pressed, the previous fragment opens.
I searched for solutions and there are quite a few like using getChildFragmentManager or back stack. I just don't know how to implement it for my specific state pager adapter, of which I followed a youtube video tutorial for.
SectionsStatePagerAdapter.java:
public class SectionsStatePagerAdapter extends FragmentStatePagerAdapter {
private final ArrayList<Fragment> mFragmentList = new ArrayList<>();
private final ArrayList<String> mFragmentTitleList = new ArrayList<>();
public SectionsStatePagerAdapter(#NonNull FragmentManager fm, int behavior) {
super(fm, behavior);
}
public SectionsStatePagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
public void addFragment(Fragment fragment, String title){
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
#NonNull
#Override
public Fragment getItem(int position) {
return mFragmentList.get(position);
}
#Override
public int getCount() {
return mFragmentList.size();
}
}
MainActivity.java:
public class MainActivity extends AppCompatActivity implements MyRecyclerViewAdapter.ItemClickListener {
public SectionsStatePagerAdapter mSectionsStatePagerAdapter;
private ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Fragment Stuff:
mSectionsStatePagerAdapter = new SectionsStatePagerAdapter(getSupportFragmentManager());
mViewPager = findViewById(R.id.container);
//SetUpPager:
setupViewPager(mViewPager);
}
private void setupViewPager(ViewPager viewPager){
SectionsStatePagerAdapter adapter = new SectionsStatePagerAdapter(getSupportFragmentManager());
adapter.addFragment(new MainPageFragment(),"MainPage"); //0
adapter.addFragment(new CoffeePageFragment(),"CoffeePage"); //1
adapter.addFragment(new RegularCoffeeFragment(),"RegularCoffeePage"); //2
viewPager.setAdapter(adapter);
}
public void setViewPager(int fragmentNumber){
mViewPager.setCurrentItem(fragmentNumber);
}
}
CoffeePageFragment.java:
public class CoffeePageFragment extends Fragment {
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.content_coffee_page,container,false);
btnRegularCoffee = view.findViewById(R.id.regular_coffee_button);
btnRegularCoffee.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
((MainActivity)getActivity()).setViewPager(2);
}
});
return (view);
}
}
In conclusion, how do I make it so when the device back button is pressed, it will go back to the previous fragment?
In previous versions of the AppCompatActivity implementation it was enough to override onBackPressed() in your activity, newer versions dictate to implement the OnBackPressedCallback, like shown here: https://developer.android.com/reference/androidx/activity/OnBackPressedDispatcher.html
public class FormEntryFragment extends Fragment {
#Override
public void onAttach(#NonNull Context context) {
super.onAttach(context);
OnBackPressedCallback callback = new OnBackPressedCallback(
true // default to enabled
) {
#Override
public void handleOnBackPressed() {
showAreYouSureDialog();
}
};
requireActivity().getOnBackPressedDispatcher().addCallback(
this, // LifecycleOwner
callback);
}
}
It might still be ok to use onBackPressed on the Activity level, though.

How to know when an activity has finish loaded

I have an activity who load a list of data, this activity its a TabActivity with 3 Tabs, all tabs load a diferent data type.
But the data may be really a bunch of data, for that reason my activity may take a lot of time to show itself.
I start teh activity using
Intent intent = new Intent(MainActivity.this, PcapAnalisys.class);
startActivity(intent);
Then, when the activity is loading shows a black screen, and after a few seconds show the content properly.
There is a way on how to show a message like: "Loading activity... please wait" or something?
This is my code for a my TabActivity:
public class PcapAnalysis extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;
private ViewPager mViewPager;
private TabLayout tabLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pcap_analysis);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mViewPager = (ViewPager) findViewById(R.id.container);
tabLayout = (TabLayout) findViewById(R.id.tabs);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
//fab.setImageResource(R.drawable.ic_attach_file_white_24dp);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
FileChooserDialog dialog = new FileChooserDialog(PcapAnalysis.this);
dialog.show();
dialog.addListener(new FileChooserDialog.OnFileSelectedListener() {
#Override
public void onFileSelected(Dialog source, File file) {
source.hide();
Toast.makeText(source.getContext(),
"File selected: " + file.getAbsolutePath(),
Toast.LENGTH_LONG).show();
Log.i("Archivo seleccionado", file.getAbsolutePath());
new AsyncTask_load(PcapAnalysis.this, file.getAbsolutePath()).execute();
}
public void onFileSelected(Dialog source, File folder, String name) {
source.hide();
Toast.makeText(source.getContext(),
"File created: " + folder.getName() + "/" + name,
Toast.LENGTH_LONG).show();
}
});
}
});
new Task().execute();
}
#Override
public void recreate()
{
super.recreate();
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_pcap_analysis, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/*public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
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;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_pcap_analysis, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}*/
private class Task extends AsyncTask<Void, Integer, Void> {
private ProgressDialog pDialog;
#Override
protected void onPreExecute() {
pDialog = new ProgressDialog(PcapAnalysis.this);
pDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
pDialog.setMessage("Procesando...");
pDialog.setCancelable(true);
pDialog.setMax(100);
pDialog.setCanceledOnTouchOutside(false);
pDialog.show();
}
#Override
protected Void doInBackground(Void... voids) {
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager.setOffscreenPageLimit(3); //cuantas paginas se precargan
mViewPager.setAdapter(mSectionsPagerAdapter);
tabLayout.setupWithViewPager(mViewPager);
//publishProgress(progress);
return null;
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected void onPostExecute(Void result) {
pDialog.dismiss();
}
}
public class SectionsPagerAdapter extends FragmentPagerAdapter {
private Fragment http = new HttpList();
private Fragment dns = new DnsList();
private Fragment ip = new IpList();
private Fragment resume = new ResumeList();
SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
//return PlaceholderFragment.newInstance(position + 1);
switch (position) {
case 0:
return http;
case 1:
return dns;
case 2:
return ip;
case 3:
return resume;
}
return null;
}
#Override
public int getCount() {
return 4;
}
#Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "HTTP";
case 1:
return "DNS";
case 2:
return "RESOURCE IP";
case 3:
return "RESUME";
}
return null;
}
}
}
As you can see this activity use fragments to show the data, and each fragment has a for cicle to load the data (that is in a String array).
Also I use a AsyncTask trying to solve this problem, but is not working. Please help!

Reset RecyclerView adapter from another Fragment

I have a Fragment that contains a RecyclerView. I am trying to implement a filter on the RecyclerView. The filter UI opens a new Fragment Dialog where the user will input a value. Once the user hits the Search Button in the Fragment Dialog, the value should be returned to the RecyclerView Fragment and the existing data in the view should be cleared. I want to re-populate the RecyclerView with the new set of data that I will obtain from the server. My problem is that, I have a method called resetAdapterDetails() in the RecyclerView Fragment which works as expected if called from the RecyclerView Fragment itself. But, when I try to call the same method from the Fragment Dialog, I get an exception:
transactionList.clear(); --> is trying to clear a list which is null
Though the data is still visible in the RecyclerView.
The RecyclerView Fragment:
public class TransactionHistoryFragment extends Fragment implements SearchView.OnQueryTextListener, DateRangePickerFragment.OnDateRangeSelectedListener{
private RecyclerView recyclerview;
private TransactionHistoryAdapter adapter;
private List<Transaction> transactionList;
public TransactionHistoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_transaction_history, container, false);
recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerview.setLayoutManager(layoutManager);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
getTransactionHistory("");
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.transactions_history_menu, menu);
final MenuItem searchItem = menu.findItem(R.id.action_search);
final SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
searchView.setOnQueryTextListener(this);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.filter_date:
FragmentManager fmDate = getActivity().getFragmentManager();
DateRangePickerFragment dialogFragmentDate = DateRangePickerFragment.newInstance(this, true);
dialogFragmentDate.show(fmDate, "Sample Fragment");
return true;
case R.id.filter_mobile:
FragmentManager fmMobile = getActivity().getFragmentManager();
SearchMobileFragment dialogFragmentMobile = new SearchMobileFragment ();
dialogFragmentMobile.show(fmMobile, "Sample Fragment");
//resetAdapterDetails();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onQueryTextChange(String newText) {
final List<Transaction> filteredModelList = filter(transactionList, newText);
adapter.setFilter(filteredModelList);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
//for filtering the list
private List<Transaction> filter(List<Transaction> models, String query) {
query = query.toLowerCase();final List<Transaction> filteredModelList = new ArrayList<>();
for (Transaction model : models) {
final String text = model.getTxnStatus().toLowerCase();
if (text.contains(query)) {
filteredModelList.add(model);
}
}
return filteredModelList;
}
//for populating the list
private void getTransactionHistory(String agentId){
GetTransactionHistoryTask task = new GetTransactionHistoryTask("agent1", "password");
task.getTransactionsByAgent("OU23","OU230000000123456789").subscribe(transactionHistoryResponse -> {
if(transactionHistoryResponse != null && transactionHistoryResponse.getTransactions() != null && transactionHistoryResponse.getTransactions().size() > 0 && transactionHistoryResponse.getErrors().size() == 0){
transactionList = transactionHistoryResponse.getTransactions();
adapter = new TransactionHistoryAdapter(transactionList);
recyclerview.addItemDecoration(new DividerItemDecoration(getActivity(), LinearLayoutManager.VERTICAL));
recyclerview.setAdapter(adapter);
onClickListnerRecyclerView();
}
else{
}
}, e -> e.printStackTrace());
}
private void onClickListnerRecyclerView() {
recyclerview.addOnItemTouchListener(
new RecyclerItemClickListener(getActivity(), new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
try {
final Transaction transactionModel= (Transaction) adapter.getObjectAt(position);
Intent i = new Intent(getActivity(), TransactionDetailsActivity.class);
i.putExtra("transaction_object",transactionModel);
startActivity(i);
}
catch (Exception e){
Log.e("List issue", e.toString());
}
}
})
);
}
#Override
public void onDateRangeSelected(int startDay, int startMonth, int startYear, int endDay, int endMonth, int endYear) {
}
public void fetchDateRange(String startDate, String endDate) {
Log.e("DateRange",startDate + "\n" + endDate);
}
public void fetchMobileNumber(String mobileNumber) {
Log.e("Mobile",mobileNumber);
resetAdapterDetails();
}
public boolean resetAdapterDetails(){
try {
transactionList.clear();
adapter.notifyDataSetChanged();
recyclerview.setAdapter(adapter);
} catch (Exception e) {
Log.e("Reset Error", ""+e.getMessage());
}
return true;
}
}
The Dialog Fragment:
public class SearchMobileFragment extends DialogFragment {
EditText mMobileNumberEditText;
Button search_button;
public SearchMobileFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search_mobile, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mMobileNumberEditText = (EditText) view.findViewById(R.id.mobile_number_editText);
search_button = (Button) view.findViewById(R.id.search_button);
search_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
dismiss();
TransactionHistoryFragment obj = new TransactionHistoryFragment();
obj.fetchMobileNumber(mMobileNumberEditText.getText().toString());
}
});
}
}
The fetchMobileNumber() method in the TransactionHistoryFragment (RecyclerView Fragment) is called through the fetchMobileNumber() method which is called from the SearchMobileFragment (Dialog Fragment).
Where am I going wrong? Why the transactionList.clear(); is throwing the null pointer exception?
You are getting the issue because you are creating new TransactionHistoryFragment instance search_button click in SearchMobileFragment. Which makes it's all variables null and initialize it again and here your transactionList becomes null.
You can achieve the same thing easily with different way also. As the place of SearchMobileFragment as a DialogFragment you can make it as Activity and start it as startActivityForResult from your TransactionHistoryFragment and implement onActivityResult callback to doing the fiteration.
But right now in your case you can manage it in different ways also:
First way:
As you are doing in your DialogFragment
search_button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
dismiss();
/*TransactionHistoryFragment obj = new TransactionHistoryFragment();
obj.fetchMobileNumber(mMobileNumberEditText.getText().toString());*/
}
});
Don't do the call for fetchMobileNumber here, in onResume of your TransactionHistoryFragment you should make a call for this. On the click of search_button save the filter data to SharedPreferences and use that in onResume of the TransactionHistoryFragment for filtering and after that clear this saved data from SharedPreferences onPause of this fragment.
You should remove
transactionList.clear();
of code from resetAdapterDetails() in TransactionHistoryFragment, because after search filter you will get updated transactionList which is already passed to adapter then forcefully no need to clear it. Or have a check before clearing it like:
if(transactionList!=null){
transactionList.clear();
}
Second way: Using BroadcastReceiver you can achieve the same thing.
Register a receiver in your TransactionHistoryFragment and sendBroadcast from SearchMobileFragment. In onReceive of the TransactionHistoryFragment do the filtration process.
I had resolved the above issue in a different way. In the Dialog Fragment I have implemented a View.OnClickListener and have created an Interface to initialize the same from the RecyclerView Fragment. I am posting the complete source codes below; the SearchMobileFragment now looks like:
public class SearchMobileFragment extends DialogFragment implements View.OnClickListener{
private OnMobileNumberSelectedListener onMobileNumberSelectedListener;
EditText mMobileNumberEditText;
Button mSearchButton;
public SearchMobileFragment() {
// Required empty public constructor
}
public static SearchMobileFragment newInstance(OnMobileNumberSelectedListener callback) {
SearchMobileFragment searchMobileFragment = new SearchMobileFragment();
searchMobileFragment.initialize(callback);
return searchMobileFragment;
}
public void initialize(OnMobileNumberSelectedListener callback) {
onMobileNumberSelectedListener = callback;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_search_mobile, container, false);
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
mMobileNumberEditText = (EditText) root.findViewById(R.id.mobile_number_editText);
mSearchButton = (Button) root.findViewById(R.id.search_button);
mSearchButton.setOnClickListener(this);
return root;
}
#Override
public void onStart() {
super.onStart();
if (getDialog() == null)
return;
getDialog().getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);
}
public void setOnMobileNumberSelectedListener(OnMobileNumberSelectedListener callback) {
this.onMobileNumberSelectedListener = callback;
}
#Override
public void onClick(View v) {
dismiss();
onMobileNumberSelectedListener.onMobileNumberSelected(mMobileNumberEditText.getText().toString());
}
public interface OnMobileNumberSelectedListener {
void onMobileNumberSelected(String mobileNumber);
}
}
The RecyclerView Fragment modifications:
public class TransactionHistoryFragment extends Fragment implements SearchView.OnQueryTextListener,
DateRangePickerFragment.OnDateRangeSelectedListener, SearchMobileFragment.OnMobileNumberSelectedListener{
private RecyclerView recyclerview;
private TransactionHistoryAdapter adapter;
private List<Transaction> transactionList;
SearchView search;
public static final String TIMERANGEPICKER_TAG = "timerangepicker";
public TransactionHistoryFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_transaction_history, container, false);
recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerview.setLayoutManager(layoutManager);
return view;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setHasOptionsMenu(true);
getTransactionHistory();
}
#Override
public void onResume() {
Log.e("onResumeTHF","invoked");
super.onResume();
}
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.transactions_history_menu, menu);
search = (SearchView) menu.findItem(R.id.action_search).getActionView();
search.setOnQueryTextListener(this);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.filter_date:
FragmentManager fmDate = getActivity().getFragmentManager();
DateRangePickerFragment dialogFragmentDate = DateRangePickerFragment.newInstance(this, true);
dialogFragmentDate.show(fmDate, "Sample Fragment");
return true;
case R.id.filter_mobile:
FragmentManager fmMobile = getActivity().getFragmentManager();
SearchMobileFragment dialogFragmentMobile = SearchMobileFragment.newInstance(this);
dialogFragmentMobile.show(fmMobile, "Sample Fragment");
return true;
default:
return super.onOptionsItemSelected(item);
}
}
#Override
public boolean onQueryTextChange(String newText) {
Log.e("newText",newText);
final List<Transaction> filteredModelList = filter(transactionList, newText);
adapter.setFilter(filteredModelList);
return true;
}
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public void onMobileNumberSelected(String mobileNumber) {
Log.e("mobileNumber",mobileNumber);
resetAdapterDetails();
}
public boolean resetAdapterDetails(){
try {
transactionList.clear();
adapter.notifyDataSetChanged();
recyclerview.setAdapter(adapter);
} catch (Exception e) {
Log.e("Reset Error", ""+e.getMessage());
}
return true;
}
}
Happy coding!
The null pointer exception is because when you create a new TransactionHistoryFragment using new onViewCreated is not called and hence transactionList is never initialized. You can create a setter for the list or pass it as a constructor to the fragment to fix this

Modify Fragment's views from MainActivity

I am trying to implement swipe views with android. I am using a ViewPager with two tabs containing fragments. In my onCreate() method, I am trying to read from a sharedPrefferences and according to what i am getting, i want to change text and visibility to some child views of the parent view of the first fragment. Unfortunately i am always getting NullPointerException when i am trying to access fragments views.
My sample code from the one of the two fragments is given below. Could you please help me ? Is there a better way to do so?
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
actionBar = getActionBar();
context = getApplicationContext();
myTabPagerAdapter = new TabPagerAdapter(getSupportFragmentManager());
myViewPager = (ViewPager) findViewById(R.id.pager);
myViewPager.setAdapter(myTabPagerAdapter);
myViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
Toast.makeText(MainActivity.this, "Selected page position: " + position, Toast.LENGTH_SHORT).show();
getActionBar().setSelectedNavigationItem(position);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
ActionBar.TabListener tabListener = new ActionBar.TabListener() {
#Override
public void onTabReselected(android.app.ActionBar.Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) {
myViewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(android.app.ActionBar.Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
};
actionBar.addTab(actionBar.newTab().setText("Spot Position").setTabListener(tabListener));
actionBar.addTab(actionBar.newTab().setText("Track Vehicle").setTabListener(tabListener));
//Get saved latitude and longitude from sharedPreferences
sharedPref = context.getSharedPreferences("net.ddns.drimou.bachelorthesis", Context.MODE_PRIVATE);
editor = sharedPref.edit();
}
#Override
protected void onStart() {
super.onStart();
getSharedPreferencesOnStart();
}
public void getSharedPreferencesOnStart() {
String s = myTabPagerAdapter.makeFragmentName(myViewPager.getId(),myViewPager.getCurrentItem());
SpotPosition sp = (SpotPosition) myTabPagerAdapter.getItem(0);
sp.setSettings();//In this call i am getting null pointer
...}
Fragment A
public class SpotPosition extends Fragment {
TextView locationTextView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View spotPosition = inflater.inflate(R.layout.spot_position, container, false);
return spotPosition;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
public void setSettings(){
locationTextView = (TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
locationTextView.setVisibility(View.VISIBLE);
locationTextView.setText("Hello");
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
TabPagerAdapter
public class TabPagerAdapter extends FragmentPagerAdapter {
SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();
private View mCurrentView;
private SpotPosition sp = null;
private static int NUM_ITEMS = 2;
public TabPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
switch (i) {
case 0:
//Fragment for SpotPosition myViewPager
return new SpotPosition();
case 1:
//Fragment for TrackVehicle myViewPager
return new TrackVehicle();
}
return null;
}
#Override
public int getCount() {
return NUM_ITEMS; //Number of Tabs
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment fragment = (Fragment) super.instantiateItem(container, position);
registeredFragments.put(position, fragment);
return fragment;
}
#Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
sp = (SpotPosition)object;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
registeredFragments.remove(position);
super.destroyItem(container, position, object);
}
#Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "Spot Position";
case 1:
return "Track Vehicle";
default:
return null;
}
}
public String makeFragmentName(int viewId, int index) {
return "android:switcher:" + viewId + ":" + index;
}
public Fragment getRegisteredFragment(int position) {
return registeredFragments.get(position);
}
#Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
public View getCurrentView(){
return this.mCurrentView;
}
public SpotPosition getCurrentSpotPosition(){
return this.sp;
}
Feel free to ask if something is not understood. Thank you
As far as I understand you call setSettings from you activity, to change views in you fragment. You did not provide stacktrace and i assume you problem - attempt to change view after onPause was called in offcreen fragment. There are several ways to deal with it.
First of all dont call to views dirrectly.
On activity
public void getSharedPreferencesOnStart() {
String s = myTabPagerAdapter.makeFragmentName(myViewPager.getId(),myViewPager.getCurrentItem());
SpotPosition sp = (SpotPosition) myTabPagerAdapter.getItem(0);
// sp.setSettings();//In this call i am getting null pointer
SharedPreferences prefs = getSharedPreferences("message",MODE_PRIVATE);
Editor editor = prefs.edit();
editor.putBoolean("say_hello",true")
editor.commit();
...}
in fragments
#Override
public void onResume(){
super.onResume();
SharedPreferences prefs =
getActivity().getSharedPreferences("message", Context.MODE_PRIVATE);
{
//this block is used for offsreen fragment, it will get update, when it go to forescreen
boolean sayHello = prefs.getBoolean("say_hello", false);
if(sayHello){
locationTextView =
(TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
locationTextView.setVisibility(View.VISIBLE);
locationTextView.setText("Hello");
}else{
// say something elese
}
}
{
//this listener is for forescreen fragment, as soon as shared preferences will be updated,
// listerner willbe called and you can update your view depending on changed parameters
prefs.registerOnSharedPreferenceChangeListener(
new OnSharedPreferenceChangeListener(){
#Override
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key
){
if(key.equals("say_hello")){
boolean sayHello = sharedPreferences.getBoolean("say_hello", false);
if(sayHello){
locationTextView =
(TextView) myView.findViewById(R.id.mainTextView);//NullPointerException here
locationTextView.setVisibility(View.VISIBLE);
locationTextView.setText("Hello");
}else{
// say something elese
}
}
}
}
);
}
}
You also can use Otto bus it is still unsutable for activity to fragment communication, as fragment can be in !isResumed state, but it is usefull fro fragment -activity comunication.
If you need some complex state tracking for each fragment and activity separatly, I'd recomment to use sqlDatabase and CursorLoaders. It will give you good controll over states and instan comunication.
Edit:
Its not that you cannot pass view from fragment to activity with getters.
Problem - you cannot garanty, that you completly aware of state of the fragment and a view. You try to update views on onStart of activity, which is call earlier, then fragmentsonStart, because fragment have to be generated by adapter and go through attachement process. (to find yout if fragment is attached to activity, you have to set listener in activity and call it ononActivityAttached` of fragment. See android studio activity with fragment template). Thus, when you call to change views, fragment and views probably did not exist.
Futhermore you should read about fragment and activity lifecycle and read about context ( espesialy why strong referencing views in unrelated context holder lead to sever memmory leaks and lificle errors

Tabs with Fragment life cycle

in my app i have a Tabs with fragment classes. i trying to refresh listView in "fragment a" with the new data i insert.
In "fragment b" i have EditText and Button ,that inserting text to the database.
in "fragment a" i have the ListView with the dataBase rows. when "fragment a" is "OnCreateView" i just put the dataBase on a "ArrayList" and past it to my baseAdapter.
but "onCreateView" not refreshing my new data every time i get into the "fragment a" else i goes to "fragment c" and "onDestroy" call on "fragment a".
so my result it was to call : "setUserVisibleHint" override method, and check if it is visible and refreshing the list.
but i dont think it is the good practice .
what should i do?
Class a
public class ListFragment extends Fragment{
basAdapterCustom adapter;
ListView lv;
ArrayList<Clock> list;
private DbHandler hand;
Context context;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.list_fragment, container, false);
context = getActivity();
Log.d(TAG, "onCreateView");
hand = new DbHandler(context);
list = new ArrayList<Clock>();
lv = (ListView) v.findViewById(R.id.listOfShifts);
adapter = new basAdapterCustom(list, getActivity());
lv.setAdapter(adapter);
refreshList();
return v;
}
//like on "resume":
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
// Make sure that we are currently visible
if (this.isVisible()) {
refreshList();
if (!isVisibleToUser) {
// TODO stop
}
}
}
private void refreshList() {
list = hand.getByWorkName();
adapter = new basAdapterCustom(list,getActivity());
lv.setAdapter(adapter);
}
class b:
public class ClockFragment extends Fragment{
DbHandler hand;
Context context;
#Override
public View onCreateView(LayoutInflater inflater,
#Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.clock, container,false);
context = getActivity();
hand = new DbHandler(context);
return v;
}
// ADD to .Db
public void addToDb(View v){
hand.add(new Clock(0, dateDay));
}
}
class mainActivity:
public class MainActivity extends FragmentActivity implements ActionBar.TabListener, OnPageChangeListener{
public static final String TAG = "myClock";
String[] tabMenu = {"FRAG A","FRAG B","FRAG C"};
private ViewPager viewPager;
private TabPagerAdapter mAdapter;
private ActionBar actionBar;
#SuppressLint("NewApi")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(MainActivity.TAG, "OnCreate = MainActivity (Pager");
viewPager = (ViewPager) findViewById(R.id.pager );
actionBar = getActionBar();
mAdapter = new TabPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
for (String tabsNames : tabMenu) {
actionBar.addTab(actionBar.newTab().setText(tabsNames).setTabListener(this));
}
viewPager.setOnPageChangeListener(this);
}
// public void transDialog(){
// Dialog mDialog = new Dialog(this, android.R.style.Theme_Translucent_NoTitleBar_Fullscreen);
// }
#Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
viewPager.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
#Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
}
#Override
public void onPageScrollStateChanged(int arg0) {
}
#Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
#Override
public void onPageSelected(int position) {
actionBar.setSelectedNavigationItem(position);
}
}
PagetAdapter.class
public class TabPagerAdapter extends FragmentPagerAdapter {
private static final String TAG = "myClock";
public TabPagerAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
#Override
public Fragment getItem(int index) {
Log.d(TAG, " CLASS : TabPagerAdapter");
switch (index) {
case 0:
return new ListFragment();
case 1:
return new ClockFragment();
case 2:
return new SettingFragment();
default:
break;
}
Log.d(TAG, " CLASS : TabPagerAdapter = "+index);
return null;
}
#Override
public int getCount() {
return 3;
}
}
Please help me i hope you are understand my problem...
You want to update listView in fragment A, after insert data in fragment b? ThenĀ  you have a few solutions to choose:
1. Implement communications between fragments via activity. Then B insert date, it send message to activity, that data need to be updated. Then fragment A started, it's ask activity to need update data. For details on implementing this communication check link.
2. Use some bus library, EventBus for example. Then fragment B insert data, it post 'data changed' event to bus. Fragment A checks on start if this event occurs.
3. Use Loaders which "monitor the source of their data and deliver new results when the content changes."

Categories

Resources