Ok so i tried to learn of all These other questions here, but i am not getting the hang of it, so i decided to ask by myself.
I got a Main Activity with different Fragments for changing the views (used the Android Standard sidebar activity template). From there the user creates Tasks via a separate Acitivty which Returns the values. In the Main Activity the Tasks are getting stored into the SQLite-database. So far it works.
Now i have the Fragment TaskList with the corresponding layout TaskList_main.xml. In this XML file i got a simple ListView which i want to fill with the values from the database. My Problem is where to write that method and when to Access it. the method would be
public void showAllListEntries() {
List<TaskData> TaskList = datasource.getAllTasks();
//Daten werden im ArrayAdapter gespeichert
ArrayAdapter<TaskData> TaskListArrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, TaskList);
ListView TaskDataListView = (ListView) findViewById(R.id.TaskListView);
TaskDataListView.setAdapter(TaskListArrayAdapter);
}
My Fragment is empty like this atm
public class TaskList extends Fragment {
View view;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_main_tasklist, container, false);
return view;
}
}
I can also send the main Activity if you like but it's a bit messy
So can someone tell me how i get this to work? And did i explain my Problem clearly?
You can do it in onCreateView. But you should make an async call to get the tasks to display and have your fragment as a listener. When you get the tasks you can create your adapter and attach it to the ListView.
And you should have a ProgressBar in TaskList_main.xml (which should be renamed to task_list_fragment.xml, I don't think there is a naming convention for layouts, but this is quite used) and hide it when you receive the data.
Related
I'm kinda new to Android developpement and I use the 'Navigation' library.
Starting from my first fragment (which is a recyclerview that fetch data from an API), if I navigate to another fragment, the navigation controller destroy the first fragment and create the second fragment and show it. If I want to return to the first one (with the left arrow or the back button), it destroy de second fragment and create the first from scratch, making it reload all the data and using bandwith.
I have read many solutions for this but they are all fastidious :
using mvvm
write my own navigation controller
using mvp
I'd like to know what's the better way to retrieve data back without calling again my API.
My first fragment :
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
AnnoncesViewModel annoncesViewModel = new ViewModelProvider(this).get(AnnoncesViewModel.class);
root = inflater.inflate(R.layout.fragment_annonces, container, false);
ctx = root.getContext();
recyclerView = root.findViewById(R.id.listeannonce_rv);
annoncesViewModel.getAnnonces().observe(this, data-> {
recyclerViewAdapter = new ListeAnnoncesAdapter(data, ctx, AnnoncesFragment.this);
recyclerView.setLayoutManager(new LinearLayoutManager(root.getContext()));
recyclerView.setAdapter(recyclerViewAdapter);
});
return root;
}
The viewmodel :
public class AnnoncesViewModel extends ViewModel {
MutableLiveData<ArrayList<Annonce>> annonces;
ArrayList<Annonce> AnnonceArrayList;
public AnnoncesViewModel() {
annonces = new MutableLiveData<>();
AnnonceArrayList = new ArrayList<>();
annonces.setValue(AnnonceArrayList);
}
public MutableLiveData<ArrayList<Annonce>> getAnnonces() {
return annonces;
}
}
For navigation, i use
navController.navigate(R.id.frag1_to_frag2);
or
navController.navigate(R.id.nav_frag2);
But it doesn't change anything.
At the moment, the data is retrieved when I press a button.
Thanks for help !
The ViewModel approach is the right choice. The problem is that when you navigate to the new fragment, the AnnoncesViewModel is getting destroyed also because you are passing the Fragment context to the ViewModelProvider. To keep the ViewModel after navigating to other fragment pass Activity context to the the provider like:
ViewModelProviders.of(requireActivity()).get(AnnoncesViewModel::class.java)
This will keep the ViewModel "alive" when you launch again your Fragment instead of creating a new AnnoncesViewModel every time the Fragment is created.
I have a search bar inside my 'main' layout, i call this layout by returning it with fragment acitivity after calling by my "MainActivity.java".
My question is, how can i add function for the searchbar so i will be able to search from my database? i can only display the layout and i don't know where do i need to put my function for searching data from my database.here is my code from my 'main.java'
public class Main extends Fragment{
public Main(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.main, container, false);
return rootView;
}
}
Thanks a lot!
Can you try to extends ActionBarActivity and add the search as one the action item in the Actionbar , or toolbar in new V7 widget to take advantage of new material design ?
use the searchview widget, google recommend that you insert the search widget as an action view in the Action Bar
I recently recently ran into an issue while setting up a viewpager with 3 fragments. When the application ran it crashed with a
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first
Here is the code for creating list list of fragments to pass to the pageAdapter.
private Vector<Fragment> getFragments() {
Vector<Fragment> list = new Vector<Fragment>();
list.add(new Fragment1());
list.add(new Fragment2());
list.add(new Fragment3());
return list;
Each of the fragments were essentially the same except for a being created with different layouts. Here was the original code I had for one of the fragments.
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = getActivity().getLayoutInflater().inflate(R.layout.fragment1, container);
return v;
}
}
But when I ran it like this it kept crashing with the IllegalStateException. I found that the issue was coming from the fragments being created. After some Googling I tried changing the code for the fragment to this.
public class Fragment1 extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = getActivity().getLayoutInflater().inflate(R.layout.fragment1, container, false);
return v;
}
}
This resolved the issue and I no longer got the IllegalStateException except I have no idea how this worked. What exactly does this boolean do? And what does this exception mean? I had tried adding the method call like it suggusted but that did not resolve it. Also I tried changing this boolean to true and I got the same error again. The android docs say its attachToRoot but isn't that what I want to do? Attach my 3 fragments to the rootview, which is the viewpager? If anyone could explain this it would be greatly appreciated.
The boolean parameter of the 3-arg version of LayoutInflater.inflate() determines whether the LayoutInflater will add the inflated view to the specified container. For fragments, you should specify false because the Fragment itself will add the returned View to the container. If you pass true or use the 2-arg method, the LayoutInflater will add the view to the container, then the Fragment will try to do so again later, which results in the IllegalStateException.
I am not entirely sure this is the right SE to ask this on but I am wondering if this is expected when developing for android. I am ending up with a larger containing class and then a significant amount of nested/newed anonymous classes for callbacks within callbacks. I am wondering if this is expected or if there is a better way of doing this as the amount of nested classes is starting to lead to very convoluted code.
This is just a dialog fragment that has some settings on it. When you click on a setting it populates a list view with the appropriate options and when you select an option it updates the value that you clicked on. It is a DialogFragment with a nested anonymous OnClickListener() that then assigns a nested anonymous OnItemClickListener() to a ListView type of object. This allows me to use the ListView object for multiple settings with having to duplicate the ListView for each one of them (I just bind a new adapter and OnItemClickListener to it).
class MyDialogFragment extends DialogFragment
{
protected View _root;
protected ListView _listViewSomeSettingOptions;
protected TextView _textViewSomeSetting;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
_root = inflater.inflate(R.layout.layout_for_dialog, container, false);
_listViewSomeSettingOptions = (ListView)_root.FindViewById(R.id.listViewSettingOptions);
_textViewSomeSetting.setOnClickListener(new OnClickListener()
{
protected ArrayList<String> _someSettingOptions = new ArrayList<String>();
// Fill _someSettingOptions with a list of options
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, _someSettingOptions);
_listViewSomeSettingOptions.setAdapter(adapter);
_listViewSomeSettingOptions.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
_textViewSomeSetting.setText(_someSettingOptions.get(position));
}
}
}
}
}
Is this just how it goes? Should I be making custom controls that implement the listeners instead of using the anonymous ones? This DialogFragment is approaching 1000 lines all in onCreateView now handling the different options and display updates of a user tweaking the setting options and its just tingling my "Maybe this is not the best design" sense. I guess besides Upkeep I am wondering if there is a drawback to this form of development.
Afternoon all,
I'm currently learning all about fragments and their use in android apps. I'm trying to populate a listView with an array of Strings. This sort of idea worked when I was populating the list without using fragments but at the moment it's throwing a runtime exception "Unable to start activity". A simple point at where to look would be much appreciated as I can't figure out the logcat reading.
The fragment is thus:
public class setupFragment extends Fragment {
#Override
public void onAttach(Context context) {
super.onAttach(context);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_setup, container, false);
ListView listView = (ListView)getView().findViewById(R.id.listView); //the program seems to at this point
String[] setups = getResources().getStringArray(R.array.setups);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, setups);
listView.setAdapter(arrayAdapter);
return view;
}
}
It's my first time posting java fragments, so any posting errors I apologize for. Cursory breakpoint debugging indicates that the program is breaking on the ListView declaration.
I can post some of the logcat on request, I'm not posting it at the moment due it being long and convoluted.
Replace: ListView listView = (ListView)getView().findViewById(R.id.listView);
with: ListView listView = (ListView) view.findViewById(R.id.listView);
You can't call getView() before returning one from onCreateView().
getView() returns null.
Replace getView() with view, returned object
ListView listView = (ListView)getView().findViewById(R.id.listView);
String[] setups = getResources().getStringArray(R.array.setups);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(getActivity(),
android.R.layout.simple_list_item_1, android.R.id.text1, setups);
listView.setAdapter(arrayAdapter);
Cut this code and paste it inside onViewCreated method, you cannot get a reference of a view by calling getView() since that view is not attached to that fragment yet.
Also change your getView() to just view.
Your ListView declaration should be as follows :
ListView listView = (ListView) view.findViewById(R.id.listView);
Refer this link to know more about getView() and Fragments. Basically the getView() method returns the root view of the fragment which is nothing but the view returned by onCreateView()