This is not really a problem but I just want to know am I using a good approach?
I am developing an application, and in that app I am using fragments. Only one activity and multiple fragments. The thing is, my activity is not a FragmentActivity because I've some views "Controls" on that activity. In the mid of the activity layout I am replacing fragments. Mock up UI is shown below.
So the approach I am using is that I have a public method in my main activity loadFragment(String fragment), I call this method from any fragment to load a particular fragment. I get instance of my activity and call this method like this.
MainActivity.getInstance().laodFragment(framgnet);
Instance is basically this.
private MainActivity instance;
And
public static MainActivity getInstance(){
return instance;
}
Here my loadFragment() method.
public void loadFragment(String fragment) {
CURRENT_FRAGMENT = fragment;
switch (fragment) {
case FRAGMENT_WORK:
generalFragment = new WorkFragment();
break;
case FRAGMENT_WORK_TWO:
generalFragment = new WorkTwoFragment();
break;
case FRAGMENT_REGISTRATION:
generalFragment = new RegistrationFragment();
break;
case FRAGMENT_INTERNAL:
generalFragment = new InternalFragment();
break;
case FRAGMENT_ABSENCE:
generalFragment = new AbsenceFragment();
break;
case FRAGMENT_OVERTIME:
generalFragment = new OvertimeFragment();
break;
case FRAGMENT_HOME:
clearAllFragments();
generalFragment = new HomeFragment();
}
replaceFragment(generalFragment);
}
I just want to know am I using a good approach? if not how can I improve it?
I've already read that saving contexts in static variables is not a good approach.
Thank you.
I've already read that saving contexts in static variables is not a
good approach
Correct ! static mostly good for cache.
You can perform another alternative to make it tightly coupled like below.
1: Make an Interface to bridge-up Activity and Fragment.
interface BridgeInteface
{
public void loadFragment(String fragment);
}
2: Implement that Interface to your MainActivityand Override method loadFragment(String fragment)
3: Pass the instance of Interface as parameter into the Fragment
#Override
public void loadFragment(String fragment) {
CURRENT_FRAGMENT = fragment;
switch (fragment) {
case FRAGMENT_WORK:
generalFragment = new WorkFragment(bridgeInteface);
break;
case FRAGMENT_WORK_TWO:
generalFragment = new WorkTwoFragment(bridgeInteface);
break;
case FRAGMENT_REGISTRATION:
generalFragment = new RegistrationFragment(bridgeInteface);
break;
case FRAGMENT_INTERNAL:
generalFragment = new InternalFragment(bridgeInteface);
break;
case FRAGMENT_ABSENCE:
generalFragment = new AbsenceFragment(bridgeInteface);
break;
case FRAGMENT_OVERTIME:
generalFragment = new OvertimeFragment(bridgeInteface);
break;
case FRAGMENT_HOME:
clearAllFragments();
generalFragment = new HomeFragment(bridgeInteface);
}
replaceFragment(generalFragment);
}
4: Call method loadFragment(String fragment) from your Fragment when you need to replace Fragment
Okay I found the solution to my problem. I removed all static instances from my Fragments and Activity and replaced all method calls with Event Calls. I used Otto library for this purpose. And it is extremely useful and easy to use.
Related
I have an interface like so:
public interface IStartCamera {
void startScanning();
}
I have a fragment that implements this interface and in this fragment I have an override for this like so:
#Override
public void startScanning() {
Intent intent = new Intent(getActivity(), QrScanAcitivity.class);
startActivityForResult(intent, SQ_SCANNING_RESULT);
startActivity(new Intent(getActivity().getApplicationContext(), QrScanAcitivity.class));
}
In my activity I create an instance of this fragment when a navigation button is clicked like so:
private IStartCamera iStartCameraInFragment;
public void setStartCameraInFragment(IStartCamera IStartCameraInFragment) {
this.iStartCameraInFragment = IStartCameraInFragment;
}
fragment = new ExitFragment();
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
fragment).commit();
navigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
fragment = null;
switch (item.getItemId()){
case R.id.item_manual_scanning:
fragment = new ExitFragment();
setStartCameraInFragment(fragment); // <=== I HAVE THE PROBLEM HERE
break;
case R.id.item_reload:
fragment = new ReloadFragment();
break;
case R.id.item_add_entry_info:
fragment = new AddEntryInfoFragment();
break;
}
getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container,
fragment).commit();
return true;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.fabOpenCamera:
iStartCameraInFragment.startScanning();
break;
}
}
when I the setStartCameraInFragment(fragment) when instantiating the fragment, I get a wrong requirement since it is expecting an IStartCamera and not a fragment even though that fragment implements IStartCamera.
First of all, don't instantiate the Fragment by using the constructor. It's a good practice to use a static method, usually named 'newInstance' for instantiating Fragments, because if you'd like to pass any parameter to it later on, you will be able to do it easily.
Regarding your question, you get the error because you are trying to call the 'setStartCameraInFragment' method by using a Fragment object, while the method requires an instance of IStartCamera. What you should do (if you want to stick with this logic) is check if the Fragment is an instance of the IStartCamera interface, and after that you would be able to use it as such. Here's an example:
if (fragment instanceof IStartCamera)
setStartCameraInFragment((IStartCamera)fragment); // --> Here the fragment can be considered as an instance of IStartCamera and this will work
is this possible ? I use framelayout to display the contents of my fragment with the use of navigation drawer. What i want to happen is to keep the state of the fragment even if i go to another fragment.
I have a vague idea on whats causing the reload which is this.
private Fragment getProfileFragment() {
switch (navItemIndex) {
case 0:
// home
ProfileLO profileLO = new ProfileLO();
return profileLO;
case 1:
LocationLO locationLO = new LocationLO();
return locationLO;
case 2:
FarmGoodsLO farmGoodsLO = new FarmGoodsLO();
return farmGoodsLO;
case 3:
RentEquipLO rentEquipLO = new RentEquipLO();
return rentEquipLO;
default:
return new ProfileLO();
}
}
Is there any hack out there?
I have a drawer navigation with:
private void DisplayView (int position) {
Fragment fragment = null;
switch (position) {
case 0:
fragment = new Fragment1();
break;
case 1:
fragment = new Fragment2();
break;
case 2:
...
From an activity I can throw that fragment (fragment2 for example)? With BeginTransaction?
Thanks
A Fragment cannot exist in it's own, eg. without an Activity. It cannot be fired up with an Intent like Activities do. You have to either create a new Activity to hold your new Fragment or replace the Fragment of your current Activity with the new one.
You cannot start fragment as an activity, they need to be added to activities.
Read more in the docs here
Also, see this
Ok so,I'm new to Android programing and I have a question. I have a swipeview similar to the one in the Play Store,and I want each tab to contain a different listview fragment. I have 2 fragments ,one called LP and other PL ,lets say. How to I edit this part of code so it uses my fragments ?
#Override
public Fragment getItem(int position) {
Fragment fragment = new Fragment();
switch (position) {
case 0:
return fragment = new Fragment1();
case 1:
return fragment = new Fragment2();
case 2:
return fragment = new Fragment3();
default:
break;
}
return fragment;
EDIT : So after listening to the advice given,it still doesent work. :-?? I have 2 separate java files for my fragments and it doesent seem to work unless i copy the classes and put them inside the main activity...I may be missing something ,so please feel free to point out any posibility
#Override
public Fragment getItem(int position) {
switch (position) {
case 0:
Fragment fragment = new Fragment1();
return fragment;
case 1:
Fragment fragment = new Fragment2();
return fragment;
case 2:
ListFragment fragment = new Fragment3();//for list fragments
return fragment;
default:
break;
}
return fragment;
You could use something like this:
#Override
public Fragment getItem(int position) {
Fragment result;
switch (position) {
case 0:
result = new LPFragment();
case 1:
result = new PLFragment();
default:
result = new DefaultFragment();
}
return result
}
You just need to return an instance of whatever fragment you want for each case in the switch.
If the PL and LP classes extends from Fragment then it's fine (though you may have some need to cast them elsewhere in the code as the function returns Fragment and not your own class types)
I am using ViewPager and i am creating Fragments dynamically inside getItem method of FragmentStatePagerAdapter as follows and i want to avoid recreation of Fragment inside this method so that the application does not crash.
#Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
Fragment fragment = new Fragment();
switch (position) {
case 0:
fragment = new CourseOverViewFragment();
break;
case 1:
fragment = new CourseSchedueListFragment();
break;
case 2:
fragment = new CourseSchedueListFragment();
break;
case 3:
fragment = new CourseNoteListFragment();
break;
case 4:
fragment = new ProjectListFragment();
break;
default:
Log.i(StudyManagerDataSource.LOG_TAG, "default");
break;
}
return fragment;
}
How ever i fond this stackoverflow answer usefull. But i am not able to assign tag
inside getItem method.
Thanks!