I'm new on android developing, and I'm developing an app with SlidingMenu library from jfeinstein10, and i'm listing some top rated data on main screen...
Now i'm doing this by getting data from SQLite and putting on a ListView inside a fragment activity
HomeFragment
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.home_fragment, container, false);
new ManageSQLiteResponse((ListView)rootView.findViewById(R.id.lv_top_rate)).execute();
return rootView;
}
ManagerSQLiteResponse call:
public void updateList(ListView listView){
DietsListAdapter adapter = new DietsListAdapter(getActivity(), R.layout.single_top_rate, dietList);
listView.setAdapter(adapter);
}
And every time i switch the fragment by selecting on SlidingMenu, all the ListView is populated again, and it causes some lag, and the menu won't open or close smoothly...
So, is there some way to run AsyncTask.execute() and populate the ListView only once, and not every time the fragment is created? by this i think it will stop lagging the SlidingMenu
TVM
use this method to add fragment in your container layout.
public void replaceFragment(Fragment fragment) {
String backStateName = fragment.getClass().getName();
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
Fragment fragmentPopped = manager.findFragmentByTag(backStateName) ;
if ( fragmentPopped != null )
manager.popBackStack(backStateName, 0);
else
ft.replace(R.id.container, fragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.addToBackStack(backStateName);
ft.commit();
}
and look make a condition in code like this, if
if ( adapter.getCount() > 0 )
{
// dont add listview.setadapter() method here.
}
elsse
{
// load data in listview.
}
Related
I have bottom navigation bar implemented in MainActivity class having two fragments.I am making retrofit request in both fragments problem is when I am switching fragments and coming back to the previous one then it makes request again and previous data has lost.I don't want this I want data to be persist in fragments once request is made.
Below is my code:
MainActivity.class
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setTitle("Home");
HomeFragment fragment = new HomeFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.commit();
bottomBar = findViewById(R.id.bottomBar);
bottomBar.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.navigation_home:
HomeFragment fragment = new HomeFragment();
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
fragmentTransaction.commit();
toolbar.setTitle("Home");
return true;
case R.id.navigation_video:
VideoFragment fragment1 = new VideoFragment();
FragmentTransaction fragmentTransaction1 = getSupportFragmentManager().beginTransaction();
fragmentTransaction1.replace(R.id.container, fragment1);
fragmentTransaction1.commit();
toolbar.setTitle("Videos");
return true;
}
return false;
}
});
}
HomeFragment.class
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
recycle = view.findViewById(R.id.recycle);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
recycle.setLayoutManager(mLayoutManager);
recycle.setHasFixedSize(true);
loadFacts();
return view;
}
VideoFragment.class
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_video, container, false);
recycle = view.findViewById(R.id.recycle);
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mLayoutManager.setReverseLayout(true);
mLayoutManager.setStackFromEnd(true);
recycle.setLayoutManager(mLayoutManager);
recycle.setHasFixedSize(true);
loadVideos();
return view;
}
Someone please let me know how can I get desired result any help would be appreciated.
THANKS
I think problem here is you use fragmentTransaction.replace. So when you switch tab. It destroy current fragment and add a new fragment, your fragment create again. To solve this I recommend to use viewpager.
Once you get your data you can cache them to a Repository. Each time you need your data check if the data already exist, if not download them again.
If you see the fragment lifecycle, while recreating it starts from onCreateView and onAttach & onCreate are called only when fragment is creating for first time. So, what you can do is
Make the API call and initialization of all variables, data of which you want to persist, in onCreate method only.
Use ViewModel instead as it retains it's state even if fragment is recreated.
If both the fragments are shown as two tabs, I hope you've implemented them using ViewPager only. It retains the state by default if you swipe in between two fragments.
Make A common class and make a static variable that stores whether the page is visited first time or later and if it is visited later then dont load data else load data.
In Common class make a boolean variable
public static boolean first=false;
Then In Your Activity do this
if(Common.first==false)
{
Common.first=true;
loadVideos();
}
else
{
//dont load list
}
I use one activity multiple fragments in my app. I use a shared element animation. I have two fragments, one of them is a detail page.
I don't want to addToBackStack function for fragment transition. And the detail fragment returns without animation for some cases. (fragmentMain->fragmentDetail)
DetailFragment detailFragment = new DetailFragment();
Transition moveTransition = TransitionInflater.from(MainActivity.singleInstance)
.inflateTransition(android.R.transition.move); // android.R.transition.move
moveTransition.setDuration(400);
detailFragment.setSharedElementEnterTransition(moveTransition);
FragmentManager fragmentManager = MainActivity.getActivityFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.addSharedElement(sharedView, sharedView.getTransitionName())
.replace(R.id.mainLayout, detailFragment);
fragmentTransaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
This code works for me. I know that if I use addToBackStack, fragmentDetail->fragmentMain reveal animation works automatically. But I don't want to the use back stack.
Below code doesn't works for fragmentDetail->fragmentMain.
detailFragment.setSharedElementReturnTransition(moveTransition);
mainFragment.setSharedElementEnterTransition(moveTransition);
FragmentManager fragmentManager = MainActivity.getActivityFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction()
.addSharedElement(textView, textView.getTransitionName())
.replace(R.id.mainLayout, mainFragment);
fragmentTransaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
How can I do shared element animation for this case?
Look at your onCreateView function. If It recreate the layout, it breaks the transition id.
Solution:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
if(inflatedView != null)
return inflatedView;
inflatedView = inflater.inflate(R.layout.fragment_blank, container,
return inflatedView;
}
I'm using ViewPager and TabLayout. And ViewPager is consisted with 4 fragments(for example, I'll call the fragments' name 1, 2, 3, 4). My 2(second fragment) has a ListView, and if I click a list-item, the 2(second fragment) will be changed another view. At that time, another view is not 1, 3 or 4. That is a new view.
It is purpose to make board's category(like, sports-soccer-midfielder). So when I select sport item, the view will show another list-item(like, soccer, baseball, basketball an so on). The category will be consisted with 3 step. So i will prepare second and third view of 2(second fragment).
But I don't know how to change view or fragment. I found some clue to solve this problem in google.
That is
FragmentManager fm = getFragmentManager();
FragmentTransaction fmt = fm.beginTransaction();
View2 v2 = new View2(); // View2 is another view
fmt.replace(R.id.view1, v2);
fmt.commit();
I used that code and it succeed to change view. But only a part of view is changed. What is the problem? How can I solve that?
Here is Pic of second fragment
and this is a view when I click list-item. only a part of view is changed.
(I can't attach picture directly, so someone help please ^^ )
And this is my code of second fragment.
public class MatchingFragment extends Fragment {
View2 v2;
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.matching_fragment, container, false);
final MatchingListViewAdapter adapter = new MatchingListViewAdapter();
ListView listView = (ListView) view.findViewById(R.id.matching_list1);
listView.setAdapter(adapter);
adapter.addItem(ContextCompat.getDrawable(getActivity(), R.drawable.lock), "LOCK", "This is lock icon");
adapter.addItem(ContextCompat.getDrawable(getActivity(), R.drawable.setup), "SETUP", "This is setup icon");
adapter.addItem(ContextCompat.getDrawable(getActivity(), R.drawable.user), "USER", "This is user icon");
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
FragmentManager fm = getFragmentManager();
FragmentTransaction fmt = fm.beginTransaction();
v2 = new View2();
fmt.replace(R.id.view1, v2);
fmt.commit();
adapter.notifyDataSetChanged();
}
});
return view;
}
}
Thanks.
I think you need to start a activity when you click item on listview. because if you replace new fragment with viewpager how can you go back to previous fragment. and why you create View2() object, what is the purpose of that?
if you want to replace fragment with viewpager use this code for it, don't replace viewpager by viewpager
Fragment fragment = new FragmentOne();
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(R.id.view, fragment);
ft.commit();
I am developing an App with TabHost, which contains 4 different Tabviews. Each tabview contains different fragment views added with following code
FragmentManager manager = getSupportFragmentManager();
FragmentTransaction ft = manager.beginTransaction();
ft.replace(R.id.tabcontent, fragment);
ft.commit();
The 3rd Tab contains a Google Maps View extends SupportMapFragment.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.map_layout, container,
false);
//Calls Asynctask to fetch map location details from server
return view;
}
From AsyncTask onPostExecute, The following code is used to plot markers on Google Maps :
mFragment = new SupportMapFragment() {
#Override
public void OnActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if ((map = mFragment.getMap()) != null) {
setUpMap();
}
}
};
FragmentManager mangaer = this.getActivity()
.getSupportFragmentManager();
FragmentTransaction fragmentTransaction = mangaer
.beginTransaction();
fragmentTransaction.add(R.id.new_map_layout, mFragment);
fragmentTransaction.commit();
Now When I add map fragments for the first time, everything works normal and mapview is getting plotted on the Tab view. But while testing the App, changing the tabviews frequently without any delay, the App crashes from 3rd Tab with the following error in transaction.commit :
E/AndroidRuntime(4392): java.lang.IllegalArgumentException: No view
found for id 0x7f060218 for fragment CustomMap$4{42e3cea0 #3> id=0x7f060218}
E/AndroidRuntime(4392): at
android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:865)
Please suggest what changes I need to make to avoid the crash.
Note : The crash only happens when I change the Tabs frequently
I am Using android Library_JakeWharton_ActionBarSherlock for implementing facebook, linked-in and other application like sliding bar,
Facing a problem going to back from i.e. Fragment B - > Fragment A.
I have a fragment called Result and another one is Details, when user click on particular item in Result Detail Fragment will called.
private void switchFragment(Fragment fragment) {
if (getActivity() == null)
return;
if (getActivity() instanceof FragmentInitializer) {
FragmentInitializer fca = (FragmentInitializer) getActivity();
fca.switchContent(fragment);
}
}
used this method for navigate from one fragment to another fragment.
How can I back from Details Fragment to Result Fragment.
Below is my Result Fragments class
public class Result_Fragments extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
LinearLayout lnr_main = (LinearLayout) inflater.inflate(R.layout.result_layout, null);
getInit(lnr_main);
return lnr_main;
}
}
I have tried below code.
1) getFragmentManager().popBackStack();
2) android.support.v4.app.FragmentManager mFragmentManager = getFragmentManager();
if(mFragmentManager.getBackStackEntryCount() > 0){
mFragmentManager.popBackStack();
}
Try this code when you launch detail fragment from result fragment.
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.left_framelayout, DetailFragment);
transaction.addToBackStack(null);
transaction.commit();