ViewPagerIndicator inside a Fragment: NullPointer with Adapter - android

I've tried to use this answer to use a ViewPager with indicator inside a fragment, like so. (Just a mock up).
There's navigation spinner that changes the fragment. Each "page" would contain a ListView.
So basically I'm looking for:
SherlockFragmentActivity -> SherlockFragment -> ViewPager -> ListView
However, when I try and implement what I saw in the answer I get an error with findViewById();
I assume it's because I'm not getting the correct "context".
Here's my Fragment:
public class HomeViewFragment extends SherlockFragment {
private ViewPager mPager;
private HomePagerAdapter mAdapter;
private TitlePageIndicator mIndicator;
private Context context;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context = getSherlockActivity().getApplicationContext();
mAdapter = new HomePagerAdapter(context);
mPager = (ViewPager)context.findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mIndicator = (TitlePageIndicator)context.findViewById(R.id.indicator);
mIndicator.setViewPager(mPager);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
}
}

Step #1: Delete context = getSherlockActivity().getApplicationContext();
Step #2: Replace context.findViewById with getActivity().findViewById
Step #3: Replace all remaining occurrences of context with getActivity()
Step #4: Delete your onActivityCreated() implementation, as it is not doing anything
Step #5: Resolve that you will never again use getApplicationContext() unless you know specifically why you need it in a given circumstance

Related

Android 'FragmentManager is already executing transactions' when notifydatasetchanged runs on ui thread

I'm using a TabLayout with ViewPager. I have two tabs in my tab layout which both have a different instances of the same fragment object. Both fragments have the same recycler view layout as well.
Problem: When I load the entire activity after getting the server objects back, I'm trying to populate both tab views with the new object, but I get the following error:
java.lang.IllegalStateException: FragmentManager is already executing
transactions
. So in my main activity:
public class MyMainActivity extends FragmentActivity {
private TabLayout tabLayout;
private ViewPager viewPager;
private MyAdapter adapter;
private MyFragment fragmentA;
private MyFragment fragmentB;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_activity);
tabLayout = (TabLayout)findViewById(R.id.tab_layout);
viewPager = (ViewPager)findViewById(R.id.view_pager);
adapter = new MyAdapter(getSupportFragmentManager(), new
ArrayList<>(), new ArrayList<>());
// Instantiate the fragments here
adapter.addFragment(....A, "Title A");
adapter.addFragment(....B, "Title B");
.....
.....
.....
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
}
public void refreshPage() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// This line crashes
adapter.notifyDataSetChanged();
}
});
}
}
I tried using getChildFragmentManager but I can't because you need to call that via a fragment object. I cannot show much code as most of it is proprietary and I had to make the code as generic as possible.
When I comment out the line that crashes, my recycler view for the first tab does not refresh unless I scroll. while the second tab does not refresh at all. Did anyone have the same issue before? How did you resolve it?
P.S I'm not using any FragmentManager or transactions so I'm not sure why it gives me that exception.

Fragment views in TabLayout not yet created on activity create

I keep running into a recurring issue in many of my apps and have been using all kinds of work arounds to "solve" it, but this time I've had it and I want to figure out a real solution.
I am trying to build a tabbed layout with two tabs where each tab shows some data which should be obtained from the internet. Once the data is obtained it is cached on the device so it can be restored instantly the next time the app is opened (and will then be refreshed in the background).
To this effect I am trying to load the cached data and display it in a RecyclerView in the first tab, and I want to do this on activity create. Before I do this I obviously set up all the tab layout stuff so that the tabs should be properly loaded. The problem is that they are not, it seems the Fragments that make up the tab pages don't have their views yet, hence I cannot access the RecyclerView on them.
Here is my Activity code:
public class MainActivity extends NetworkBusActivity
{
// Views
ViewPager tabPager;
TabLayout tabLayout;
// Tab pager adapter
private ViewPagerAdapter adapter;
// Fragment one and two
private MenuFragment menuFragment;
private OrderFragment orderFragment;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Create the views
tabPager = (ViewPager) findViewById(R.id.tabPager);
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
// Setup the tab layouts
this.setupTabs();
// Show cached data
this.setCachedItems();
// Start loading new data in background
this.startLoading();
}
private void setupTabs()
{
// Create Fragments
menuFragment = new MenuFragment();
orderFragment = new OrderFragment();
// Setup adapter
adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(menuFragment, getString(R.string.title_menu));
adapter.addFragment(orderFragment, getString(R.string.title_orders));
tabPager.setAdapter(adapter);
// Setup the tab layout
tabLayout.setupWithViewPager(tabPager);
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener()
{
// not shown
});
}
private void setCachedItems()
{
// Show cached data
ArrayList<Item> items = Cache.menu.getItems();
menuFragment.setItems(items);
}
private void startLoading()
{
// Start loading in background (not shown)
}
}
It should be straightforward: create the views, create the fragments, and setup the tab layout, then load the cached data.
The MenuFragment extends a base class ItemListFragment which defines the setItems method:
public class MenuFragment extends ItemListFragment
{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.tab_menu, container, false);
return view;
}
#Override
protected ItemListAdapter getAdapter(ArrayList<Item> items, boolean categorize)
{
return new MenuListAdapter(this, R.layout.row_item, items, categorize);
}
}
public abstract class ItemListFragment extends Fragment
{
private RecyclerView recycler;
#Override
public void onViewCreated(View view, Bundle savedInstanceState)
{
super.onViewCreated(view, savedInstanceState);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getActivity());
recycler = (RecyclerView) view;
recycler.setLayoutManager(linearLayoutManager);
recycler.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
}
public void setItems(ArrayList<Item> items)
{
recycler.setAdapter(getAdapter(items, true));
}
protected abstract ItemListAdapter getAdapter(ArrayList<Item> items, boolean categorize);
}
Again straightforward: create the view in onCreateView, then obtain the RecyclerView in onViewCreated, and finally set the items with an adapter.
The problem is simple: the method setCachedItems in MainActivity is called before the onCreateView or onViewCreated methods are called in the Fragments. Hence, the RecyclerView is null and I can't set its adapter. Even though I am creating a new instance of the Fragments and adding them to a functional TabLayout before I call that method.
There seems to be some delay before the views are created, but I need to set the items already when the activity is created.
Where am I going wrong, and how do I fix it?
In onViewCreated of fragment do this
((MainActivity)getActivity).setCachedData().....
Instead of on create of activity

FragmentManager is always null

so this one really has me stumped. I am trying to create a simple ViewPager activity which has three swipe views containing a listview. I have a FragmentPagerAdapter, a ListFragment set to hold the listviews, and have defined the layout for the fragments. Here is my problem is that FragmentPagerAdapter takes a FragmentManager, so I try to pass it in like so
mFragmentPagerAdapter=new FragmentPagerAdapter(getSupportFragmentManager());
but the FragmentManager is always null, meaning that the rest of the work to set up the pager crashes the app
I have no idea why getSupportFragmentManager would return null.
Here is the code for my activity, or at least the relevant bits
public class JobListActivity extends FragmentActivity {
private ArrayList<Job> jobsQuote=new ArrayList<Job>();
private ArrayList<Job> jobsIn= new ArrayList<Job>();
private ArrayList<Job> jobsOut=new ArrayList<Job>();
private ListFragment quoteListFragment=new ListFragment();
private ListFragment inListFragment =new ListFragment();
private ListFragment outListFragment=new ListFragment();
JobFragmentPagerAdapter mFragmentPagerAdapter;
ViewPager mViewPager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_job_list);
FragmentManager fm = getSupportFragmentManager();
mFragmentPagerAdapter =
new JobFragmentPagerAdapter(fm);
mViewPager = (ViewPager) findViewById(R.id.jobs_view_pager);
mViewPager.setAdapter(mFragmentPagerAdapter);
I really appreciate any help you can provide, thanks so much for your time
Here is the tutorial I have been following from the android developer web site
http://developer.android.com/training/implementing-navigation/lateral.html
clearly I am missing something.
Figured it out. When I implement the methods from Fragment activity, I accidentily overrode getSupportFragmentManager(); to return null.

FragmentPagerAdapter and notifyDataSetChanged

How can I use notifyDataSetChanged with FragmentPagerAdapter ?
In onResume:
I used mMyFragmentPagerAdapter.notifyDataSetChanged(); but it didnt worked
But mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager()); is worked
public class Activity extends FragmentActivity{
static ViewPager mViewPager;
private MyFragmentPagerAdapter mMyFragmentPagerAdapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mViewPager = (ViewPager) findViewById(R.id.pager);
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mMyFragmentPagerAdapter);
}
private static class MyFragmentPagerAdapter extends FragmentPagerAdapter {
...
}
#Override
protected void onResume() {
super.onResume();
//WORKS
mMyFragmentPagerAdapter = new MyFragmentPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mMyFragmentPagerAdapter);
//DOESN'T WORK
mMyFragmentPagerAdapter.notifyDataSetChanged();
mViewPager.setAdapter(mMyFragmentPagerAdapter);
}
}
Populate:
public void startView() {
this.questions.clear(); // this.questions is a LinkedList
this.questions.add(q);
}
First of all, to update a ListView / ViewPager or any other kind of view and it's adapter,you need to requery the Cursor for example if you are using it to populate the view. So as in your situation, you have a ViewPager and an Adapter. So the first thing which you consider is the way you update your LinkedList. In your situations you are doing it right, but in my opinion this.quetions in your external class is different than the LinkedList you are using to populate your adapter. In this case I would suggest you don't use external class to update your adapter. If that is too hard to achieve depending on the code organisation, just be sure that you are using the same LinkedList in your Fragment and external class.
Change your adapter extends FragmentPagerAdapter to FragmentStatePagerAdapter and then the notifyDataSetChanged work fine.
It's work for me.

Android:Null Pointer in ViewPager

I am making an app in which i am using ViewPAger and my code is working fine on S2 and NOTE but i checked on Y its giving exception on viewPagerAdapter. My code is as follows:
static PagerAdapter mPagerAdapter;
static ViewPager mViewPager;
static ViewPagerIndicator mIndicator;
static String addposition;
public Context _context=this;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Create our custom adapter to supply pages to the viewpager.
mPagerAdapter = new PagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager)findViewById(R.id.pager);
mViewPager.setAdapter(mPagerAdapter); // **Null Pointer Exception**
You can not write public Context _context=this; in global. You should initialize the content in onCreate().
Edit
Actually I had not seen that you are not using the context. I think there is an issue in the ViewPager. May be you are getting null object of ViewPager. If you show your xml then we can provide a better solution

Categories

Resources