Android getListView () в ошибке фрагмента

У меня проблема с моим Android-приложением, где он сбой со следующей ошибкой при прокрутке между вкладками:

09-16 16:19:27.142 4750-4750/com.khackett.runmate E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.khackett.runmate, PID: 4750 java.lang.IllegalStateException: Content view not yet created at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) at android.support.v4.app.ListFragment.getListView(ListFragment.java:222) at com.khackett.runmate.ui.MyRunsFragment$1.done(MyRunsFragment.java:167) at com.khackett.runmate.ui.MyRunsFragment$1.done(MyRunsFragment.java:135) at com.parse.ParseTaskUtils$2$1.run(ParseTaskUtils.java:115) at android.os.Handler.handleCallback(Handler.java:739) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5254) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

Это MyRunsFragment:

 public class MyRunsFragment extends ListFragment { protected SwipeRefreshLayout mSwipeRefreshLayout; // member variable to store the list of routes the user has accepted protected List<ParseObject> mAcceptedRoutes; private int MY_STATUS_CODE = 1111; // Default constructor for MyRunsFragment public MyRunsFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_my_runs, container, false); // Set SwipeRefreshLayout component mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshLayout); // Set the onRefreshListener mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener); mSwipeRefreshLayout.setColorSchemeResources( R.color.swipeRefresh1, R.color.swipeRefresh2, R.color.swipeRefresh3, R.color.swipeRefresh4); return rootView; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { // Retrieve the accepted routes from the Parse backend retrieveAcceptedRoutes(); } @Override public void onResume() { super.onResume(); } @Override public void onListItemClick(ListView l, View v, int position, long id) { super.onListItemClick(l, v, position, id); // create the message object which is set to the message at the current position ParseObject route = mAcceptedRoutes.get(position); // String messageType = message.getString(ParseConstants.KEY_FILE_TYPE); JSONArray parseList = route.getJSONArray(ParseConstants.KEY_LATLNG_POINTS); JSONArray parseListBounds = route.getJSONArray(ParseConstants.KEY_LATLNG_BOUNDARY_POINTS); String objectId = route.getObjectId(); String routeName = route.getString(ParseConstants.KEY_ROUTE_NAME); // JSONArray ids = route.getJSONArray(ParseConstants.KEY_RECIPIENT_IDS); // Start a map activity to display the route Intent intent = new Intent(getActivity(), MapsActivityTrackRun.class); intent.putExtra("parseLatLngList", parseList.toString()); intent.putExtra("parseLatLngBoundsList", parseListBounds.toString()); intent.putExtra("myRunsObjectId", objectId); intent.putExtra("myRunsRouteName", routeName); // Start the MapsActivityDisplayRoute activity startActivityForResult(intent, MY_STATUS_CODE); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { } private void retrieveAcceptedRoutes() { // query the routes class/table in parse // get messages where the logged in user ID is in the list of the recipient ID's (we only want to retrieve the messages sent to us) // querying the message class is similar to how we have been querying users ParseQuery<ParseObject> queryRoute = new ParseQuery<ParseObject>(ParseConstants.CLASS_ROUTES); // use the 'where' clause to search through the messages to find where our user ID is one of the recipients queryRoute.whereEqualTo(ParseConstants.KEY_ACCEPTED_RECIPIENT_IDS, ParseUser.getCurrentUser().getObjectId()); // order results so that most recent message are at the top of the inbox queryRoute.addDescendingOrder(ParseConstants.KEY_CREATED_AT); // query is ready - run it queryRoute.findInBackground(new FindCallback<ParseObject>() { // When the retrieval is done from the Parse query, the done() callback method is called @Override public void done(List<ParseObject> routes, ParseException e) { // dismiss the progress indicator here // getActivity().setProgressBarIndeterminateVisibility(false); // End refreshing once routes are retrieved // done() is called from onResume() and the OnRefreshListener // Need to check that its called from the the OnRefreshListener before ending it if (mSwipeRefreshLayout.isRefreshing()) { mSwipeRefreshLayout.setRefreshing(false); } // the list being returned is a list of routes if (e == null) { // successful - routes found. They are stored as a list in messages mAcceptedRoutes = routes; // adapt this data for the list view, showing the senders name // create an array of strings to store the usernames and set the size equal to that of the list returned String[] usernames = new String[mAcceptedRoutes.size()]; // enhanced for loop to go through the list of users and create an array of usernames int i = 0; for (ParseObject message : mAcceptedRoutes) { // get the specific key usernames[i] = message.getString(ParseConstants.KEY_SENDER_NAME); i++; } // Create the adapter once and update its state on each refresh if (getListView().getAdapter() == null) { // the above adapter code is now replaced with the following line RouteMessageAdapter adapter = new RouteMessageAdapter(getListView().getContext(), mAcceptedRoutes); // Force a refresh of the list once data has changed adapter.notifyDataSetChanged(); // need to call setListAdapter for this activity. This method is specifically from the ListActivity class setListAdapter(adapter); } else { // refill the adapter // cast it to RouteMessageAdapter ((RouteMessageAdapter) getListView().getAdapter()).refill(mAcceptedRoutes); } } } }); } protected SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { // When list is swiped down to refresh, retrieve the users runs from the Parse backend retrieveAcceptedRoutes(); } }; } 

И файл макета фрагмента:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity$PlaceholderFragment"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentStart="true" android:layout_alignParentTop="true"> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_alignParentStart="true" android:layout_alignParentTop="true" android:clipToPadding="false" android:paddingBottom="@dimen/inbox_vertical_margin"/> </android.support.v4.widget.SwipeRefreshLayout> <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/empty_inbox_label" android:textSize="@dimen/default_text_size"/> </RelativeLayout> 

TabFragmentContainer

 public class TabFragmentContainer extends Fragment { // Create the FragmentPagerAdapter that will provide and manage tabs for each section. public static MyFragmentPagerAdapter myFragmentPagerAdapter; public static TabLayout tabLayout; // The ViewPager is a layout widget in which each child view is a separate tab in the layout. // It will host the section contents. public static ViewPager viewPager; @Nullable @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate tab_layout_fragment_container view and setup views for the TabLayout and ViewPager items. View view = inflater.inflate(R.layout.tab_layout_fragment_container, null); tabLayout = (TabLayout) view.findViewById(R.id.tabs); // Set up the ViewPager with the sections adapter. viewPager = (ViewPager) view.findViewById(R.id.viewpager); // Instantiate the adapter that will return a fragment for each of the three sections of the main activity myFragmentPagerAdapter = new MyFragmentPagerAdapter(getActivity(), getChildFragmentManager()); // Set up the adapter for the ViewPager viewPager.setAdapter(myFragmentPagerAdapter); // Runnable() method required to implement setupWithViewPager() method tabLayout.post(new Runnable() { @Override public void run() { tabLayout.setupWithViewPager(viewPager); viewPager.setCurrentItem(1, false); // tabLayout.getTabAt(1).select(); } }); // Return the created View return view; } } 

FragmentPagerAdapter:

 public class MyFragmentPagerAdapter extends FragmentPagerAdapter { // The context to be passed in when the adapter is created. private Context mContext; // The number of tabs in the layout. public static int numberOfTabs = 3; /** * Default constructor that accepts a FragmentManager parameter to add or remove fragments. * * @param context the context from the activity using the adapter. * @param fragmentManager the FragmentManager for managing Fragments inside of the TabFragmentContainer. */ public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) { super(fragmentManager); mContext = context; } /** * Method to return the relevant fragment for the selected tab. */ @Override public Fragment getItem(int position) { switch (position) { case 0: return new MyRunsFragment(); case 1: return new InboxRouteFragment(); case 2: return new FriendsFragment(); } return null; } /** * Method that gets the number of tabs in the layout. * * @return the number of tabs in the layout. */ @Override public int getCount() { return numberOfTabs; } /** * Method that returns the title of each tab in the layout. */ @Override public CharSequence getPageTitle(int position) { Locale locale = Locale.getDefault(); switch (position) { case 0: return mContext.getString(R.string.title_section1).toUpperCase(locale); case 1: return mContext.getString(R.string.title_section2).toUpperCase(locale); case 2: return mContext.getString(R.string.title_section3).toUpperCase(locale); } return null; } } 

Файл tab_layout_fragment_container, содержащий виджет ViewPager:

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <android.support.design.widget.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/ColorPrimaryPurple" app:tabGravity="fill" app:tabIndicatorColor="@color/ColorPrimaryPurple" app:tabMode="fixed" app:tabSelectedTextColor="@color/textColorPrimary" app:tabTextColor="@color/pressedPurpleButton"> </android.support.design.widget.TabLayout> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> </LinearLayout> 

Метод onCreate() в моей MainActivity:

 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // Initialise the DrawerLayout and NavigationView views. mDrawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout); mNavigationView = (NavigationView) findViewById(R.id.navigationDrawerMenu); // Inflate the first fragment to be displayed when logged into the app. mFragmentManager = getSupportFragmentManager(); mFragmentTransaction = mFragmentManager.beginTransaction(); mFragmentTransaction.replace(R.id.containerView, new TabFragmentContainer()).commit(); // Setup click events on the NavigationView items. // When an item is selected, replace the tab fragment container with the requested fragment. mNavigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(MenuItem menuItem) { mDrawerLayout.closeDrawers(); if (menuItem.getItemId() == R.id.navItemHome) { FragmentTransaction tabFragmentContainer = mFragmentManager.beginTransaction(); tabFragmentContainer.replace(R.id.containerView, new TabFragmentContainer()).commit(); } if (menuItem.getItemId() == R.id.navItemRunHistory) { FragmentTransaction runHistoryFragment = mFragmentManager.beginTransaction(); runHistoryFragment.replace(R.id.containerView, new RunHistoryFragment()).commit(); } if (menuItem.getItemId() == R.id.navItemSettings) { FragmentTransaction settingsFragment = mFragmentManager.beginTransaction(); settingsFragment.replace(R.id.containerView, new SettingsFragment()).commit(); } if (menuItem.getItemId() == R.id.navItemHelp) { FragmentTransaction instructionsFragment = mFragmentManager.beginTransaction(); instructionsFragment.replace(R.id.containerView, new InstructionsFragment()).commit(); } if (menuItem.getItemId() == R.id.navItemMyProfile) { FragmentTransaction myProfileFragment = mFragmentManager.beginTransaction(); myProfileFragment.replace(R.id.containerView, new MyProfileFragment()).commit(); } if (menuItem.getItemId() == R.id.navItemLogOut) { // User has selected log out option. Log user out and return to login screen. ParseUser.logOut(); navigateToLogin(); } return false; } }); // Set up the Toolbar. setupToolbar(); } 

Я getListView() другими ответами и добавил функцию onViewCreated() методу onViewCreated() но проблема все еще сохраняется … Может ли кто-нибудь указать, где я могу ошибиться?

Solutions Collecting From Web of "Android getListView () в ошибке фрагмента"

Исходя из этих фактов:

  • Исключение getListView() потому что еще нет корневого представления, когда done() вызывает getListView() .
  • done() вызывается, когда запрос, полученный методом retrieveAcceptedRoutes() получает ответ.
  • OnRefreshListener mOnRefreshListener в нескольких местах, в том числе OnRefreshListener mOnRefreshListener , который регистрируется как прослушиватель обновлений в onCreateView() до того, как появится представление корневого onCreateView() то есть до onCreateView() ).

… возможно, чтобы getListView() вызывался до появления корневого представления.

Попробуйте переместить эти 3 оператора из onCreateView() в onViewCreated() , так что прослушиватель обновлений может вызываться только при наличии корневого представления.

  // Set SwipeRefreshLayout component mSwipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swipeRefreshLayout); // Set the onRefreshListener mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener); mSwipeRefreshLayout.setColorSchemeResources( R.color.swipeRefresh1, R.color.swipeRefresh2, R.color.swipeRefresh3, R.color.swipeRefresh4); 

onViewCreated вызывается сразу после onCreateView , но вызов super.onViewCreated отсутствует, возможно, это super.onViewCreated причина вашей проблемы.

 @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // add this line back in // Retrieve the accepted routes from the Parse backend retrieveAcceptedRoutes(); } 

Удалить все эти импортные товары:

 import com.yourName.runmate.R; 

Затем выполните повторную синхронизацию и перестройте проект.

Введите описание изображения здесь

Также см. Здесь:
«Невозможно разрешить символ R» в Android Studio

редактировать

Ваша первая очевидная ошибка в вашем Main

 mFragmentManager = getSupportFragmentManager(); 

должно быть:

 mFragmentManager = getFragmentManager(); 

Или измените основную деятельность на:

MainActivity extends FragmentActivity чтобы использовать диспетчер фрагментов поддержки.


У вас много ненужного кода в вашем вопросе, большинство комментариев можно удалить и импортировать для целей этого вопроса.

То, что я придумал, – это не деятельность, которая используется. Элемент ListFragment должен быть привязан к Activity или вы пытаетесь вызвать этот вид активности до его создания.

 java.lang.IllegalStateException: Content view not yet created at android.support.v4.app.ListFragment.ensureList(ListFragment.java:328) at android.support.v4.app.ListFragment.getListView(ListFragment.java:222) 

Если вы используете Main, то вы не собираете их вместе хорошо, из того, что я вижу.

В первую очередь:

Возьмите все из своего onCreate и onCreateView (для всех фрагментов), за исключением просмотра надувных элементов.

Поместите весь дополнительный код в onViewCreated или onActivityCreated. Таким образом, никакие методы не могут быть вызваны в нулевом представлении, так как они вызываются после их создания.

Во-вторых, вам нужно разобраться в своих действиях и с тем, чего вы точно пытаетесь достичь.

Вам нужен просмотрщик страниц и список фрагментов. Просмотр страницы должен быть связан с активностью или фрагментом действия, а не с фрагментом. В противном случае нет привязки страниц страниц для просмотра.

Используйте FragmentActivity, а не фрагмент. Чтобы быть активным, вы запускаете свой ListFragment.

 public class TabFragmentContainer extends FragmentActivity { MyPageAdapter pageAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.tab_layout_fragment_container); // change to view layout. // Instantiate the adapter that will return a fragment for each of the three sections of the main activity myFragmentPagerAdapter = new MyFragmentPagerAdapter(getFragmentManager(), getFragments()); tabLayout = (TabLayout) view.findViewById(R.id.tabs); // Set up the ViewPager with the sections adapter. viewPager = (ViewPager) view.findViewById(R.id.viewpager); // Set up the adapter for the ViewPager viewPager.setAdapter(myFragmentPagerAdapter); } } 

Я бы предложил поместить это в свой список, чтобы убедиться, что ваша деятельность создана. Вам нужно будет перенести большую часть вашего кода из методов onCreate и поместить их в onViewCreated или onActivityCreated

 @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); ArrayAdapter adapter = ArrayAdapter.createFromResource(getActivity(), R.layout.my_listview)layout, android.R.layout.simple_list_item_1); setListAdapter(adapter); getListView().setOnItemClickListener(this); } 

Этот код является просто руководством, вам нужно его настроить.

Позвольте мне знать, если это помогает.

Эти вопросы и ответы отлично.

Просмотр содержимого еще не создан

Андроид Недопустимый статус содержимого содержимого исключения еще не создан?


Фрагмент же принципов применяется к фрагментам ViewPager ViewPager

Я снова прочитал ваш вопрос, тогда я предполагаю, что:

  • Ваш ListFragment уничтожается во время выполнения фоновой задачи. Поэтому, когда это будет сделано, ваш обратный вызов хотел бы обновить ListView, который больше не жив.

  • Фактически, viewPager.setOffscreenPageLimit(3); Может сделать трюк, но это не очень хорошая практика. Это заставляет ViewPager создавать и хранить больше фрагментов в памяти, что необязательно. Вот почему я голосую за этот ответ. Вы можете решить это, не делая этого.

Что вы должны делать: одна из следующих двух практик должна быть хорошей, или и то, и другое:

  • Уничтожьте свою задачу в своем onPause или любом методе жизненного цикла перед вашим onDestroyView .

  • Исключите код, в котором вы обновляете ListView внутри метода done() . Сделайте это локальным методом, где вы тщательно проверите свой ListView, и там вы должны попросить, чтобы процесс обновления выполнялся в потоке пользовательского интерфейса, чтобы избежать какой-либо проблемы с потоками. Убедитесь, что ваш getView() не является нулевым (но не вашим getListView() , поскольку он генерирует исключение, если getView () возвращает null).

Я рекомендую вам использовать оба из них, чтобы убедиться, что ваш вид по-прежнему доступен, и вы не тратите свой ресурс при выполнении задачи в invisible фрагменте. Не забывайте, что по умолчанию , как только ваш фрагмент невидим, он считается разрушенным (не всегда, например ViewPager сохраняет ссылку на 2 фрагмента, но помните об этом случае).

Надеюсь, эта помощь.

Попробуйте объявить:

 viewPager = (ViewPager) view.findViewById(R.id.viewpager); viewPager.setAdapter(myFragmentPagerAdapter); myFragmentPagerAdapter = new MyFragmentPagerAdapter(getActivity(), getChildFragmentManager()); 

до:

  tabLayout = (TabLayout) view.findViewById(R.id.tabs); tabLayout.post(new Runnable() { @Override public void run() { tabLayout.setupWithViewPager(viewPager); viewPager.setCurrentItem(1, false); // tabLayout.getTabAt(1).select(); } }); // Return the created View return view;