Android – Tab # 3 очищает представление списка из Tab # 1.

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

Мое приложение имеет 3 вкладки. Вкладка 1 имеет вид списка внутри фрагмента, а две другие вкладки – это в основном пустые фрагменты-заполнители. Когда я нажимаю на вкладку 1, а затем на вкладку 2, а затем обратно на вкладку 1, мой список выглядит так, как ожидалось. Однако, если я нажму на вкладку 3, а затем на вкладке 1, мой список списка исчезнет. Я не вижу разницы между Tab 2 и Tab 3, которые могут вызвать это.

Я добавил связанный код из своего приложения. Пожалуйста, дайте мне знать, если потребуется больше.

Любая помощь и советы были бы высоко оценены!

Моя основная деятельность:

var mCursorAdapter: DbCursorAdapter? = null class CatalogActivity : AppCompatActivity(), LoaderManager.LoaderCallbacks<Cursor> { private lateinit var mFragmentPagerAdapter: FragmentPagerAdapter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_catalog) setSupportActionBar(toolbar) // Create the adapter that will return a fragment for each of the three // primary sections of the activity. mFragmentPagerAdapter = FragmentPagerAdapter(supportFragmentManager) // Set up the ViewPager with the sections adapter. view_pager_container.adapter = mFragmentPagerAdapter view_pager_container.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs)) tabs.addOnTabSelectedListener(TabLayout.ViewPagerOnTabSelectedListener(view_pager_container)) // Setup FAB to open EditorActivity fab_button.setOnClickListener { val intent = Intent(this@CatalogActivity, EditorActivity::class.java) startActivity(intent) } // Kick off the loader loaderManager.initLoader(INGREDIENT_LOADER, null, this) } /** * Helper method to insert hardcoded ingredient data into the database. For debugging purposes only. */ private fun insertIngredient() { // Create a ContentValues object where column names are the keys, // and Rittenhouse Rye Whiskey attributes are the values. val values = ContentValues() values.put(IngredientEntry.COLUMN_INGREDIENT_NAME, "Rittenhouse Rye") values.put(IngredientEntry.COLUMN_INGREDIENT_DESCRIPTION, "Earthly with a sweet finish.") values.put(IngredientEntry.COLUMN_INGREDIENT_CATEGORY, IngredientEntry.CATEGORY_WHISKEY) values.put(IngredientEntry.COLUMN_INGREDIENT_WEIGHT, 1) // Insert a new row for Rittenhouse Rye Whiskey into the provider using the ContentResolver. // Use the {@link IngredientEntry#CONTENT_URI} to indicate that we want to insert // into the ingredients database table. // Receive the new content URI that will allow us to access Rittenhouse's data in the future. contentResolver.insert(IngredientEntry.CONTENT_URI, values) } /** * Helper method to delete all ingredients in the database. */ private fun deleteAllIngredients() { val rowsDeleted = contentResolver.delete(IngredientEntry.CONTENT_URI, null, null) Log.v("CatalogActivity", rowsDeleted.toString() + " rows deleted from ingredient database") } override fun onCreateOptionsMenu(menu: Menu): Boolean { // Inflate the menu options from the res/menu/menu_catalog.xml file. // This adds menu items to the app bar. menuInflater.inflate(R.menu.menu_catalog, menu) return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { // User clicked on a menu option in the app bar overflow menu when (item.itemId) { // Respond to a click on the "Insert dummy data" menu option R.id.action_insert_dummy_data -> { insertIngredient() return true } // Respond to a click on the "Delete all entries" menu option R.id.action_delete_all_entries -> { deleteAllIngredients() return true } } return super.onOptionsItemSelected(item) } override fun onCreateLoader(i: Int, bundle: Bundle?): Loader<Cursor> { // Define a projection that specifies the columns from the table we care about. val projection = arrayOf(IngredientEntry._ID, IngredientEntry.COLUMN_INGREDIENT_NAME, IngredientEntry.COLUMN_INGREDIENT_DESCRIPTION) // This loader will execute the DbContentProvider's query method on a background thread return CursorLoader(this, // Parent activity context IngredientEntry.CONTENT_URI, // Provider content URI to query projection, null, null, null)// Columns to include in the resulting Cursor // No selection clause // No selection arguments // Default sort order } override fun onLoadFinished(loader: Loader<Cursor>, data: Cursor) { // Update {@link DbCursorAdapter} with this new cursor containing updated ingredients data mCursorAdapter?.swapCursor(data) } override fun onLoaderReset(loader: Loader<Cursor>) { // Callback called when the data needs to be deleted mCursorAdapter?.swapCursor(null) } companion object { /** Identifier for the ingredients data loader */ private val INGREDIENT_LOADER = 0 } } 

Мой фрагмент ингредиентов:

 class IngredientsFragment : Fragment() { override fun onAttach(context: Context?) { super.onAttach(context) } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_ingredient, container, false) } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) // Set empty view on the ListView, so that it only shows when the ingredient_list_view has 0 items. ingredient_list_view.emptyView = empty_view // Setup an Adapter to create a ingredient_list_view item for each row of ingredient data in the Cursor. // There is no ingredient data yet (until the loader finishes) so pass in null for the Cursor. mCursorAdapter = DbCursorAdapter(context, null) ingredient_list_view.adapter = mCursorAdapter // Setup the item click listener ingredient_list_view.onItemClickListener = AdapterView.OnItemClickListener { _: AdapterView<*>?, _: View?, _: Int, id: Long -> // Create new intent to go to {@link EditorActivity} val intent = Intent(context, EditorActivity::class.java) // Form the content URI that represents the specific ingredient that was clicked on, // by appending the "id" (passed as input to this method) onto the // {@link IngredientEntry#CONTENT_URI}. // For example, the URI would be "content://onCreateDesigns.com.CraftCocktailRecipes.ingredients/ingredients/2" // if the ingredient with ID 2 was clicked on. val currentUri = ContentUris.withAppendedId(DbContract.IngredientEntry.CONTENT_URI, id) // Set the URI on the data field of the intent intent.data = currentUri // Launch the {@link EditorActivity} to display the data for the current ingredient. startActivity(intent) } } override fun onDetach() { super.onDetach() } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) } } 

Мой адаптер:

 class FragmentPagerAdapter(fm: FragmentManager) : SmartFragmentStatePagerAdapter(fm) { override fun getItem(position: Int): Fragment { return when (position) { 0 -> IngredientsFragment() 1 -> RecipesFragment() else -> FavoritesFragment() } } override fun getCount(): Int { // Show 3 total pages. return 3 } } 

Мой фрагмент ингредиентов:

 <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="onCreateDesigns.com.CraftCocktailRecipes.IngredientsFragment"> <ListView android:id="@+id/ingredient_list_view" android:layout_width="match_parent" android:layout_height="match_parent"/> <!-- Empty view for ingredient_list_view list --> <RelativeLayout android:id="@+id/empty_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> <ImageView android:id="@+id/empty_shelter_image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:src="@drawable/ic_empty_shelter" android:contentDescription="@string/empty_shelter" /> <TextView android:id="@+id/empty_title_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/empty_shelter_image" android:layout_centerHorizontal="true" android:fontFamily="sans-serif-medium" android:paddingTop="16dp" android:text="@string/empty_view_title_text" android:textAppearance="?android:textAppearanceMedium"/> <TextView android:id="@+id/empty_subtitle_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/empty_title_text" android:layout_centerHorizontal="true" android:fontFamily="sans-serif" android:paddingTop="8dp" android:text="@string/empty_view_subtitle_text_ingredients" android:textAppearance="?android:textAppearanceSmall" android:textColor="#A2AAB0"/> </RelativeLayout> 

Я думаю, что это функция по умолчанию для пейджера-просмотра, которая в это время установила, что приложение Adapter view-pager загружает два фрагмента , когда вы перемещаете фрагмент 1 в 3, тогда он выдает фрагмент 1 и мудрый вариант,

если вы хотите загрузить весь фрагмент в первый раз, чем написать одну строку после setAdapter

 view_pager_container.setOffscreenPageLimit(3); 

setOffscreenPageLimit () этот метод загружает все ваши три фрагмента в это время или никогда не инициализируется снова.

Может быть полезно.

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

setOffscreenPageLimit (целое)

Вы можете попробовать это два решения:

  1. Просто увеличивает значение до 2 (т.е. setOffscreenPageLimit (2))
  2. Добавьте код манипуляции списком, который устанавливает адаптер в методе setUserVisibleHint .

В ViewPager всегда отображаются текущие, левые и правые страницы (фрагмент). всякий раз, когда вы нажимаете Tab 3, фрагмент в Tab 1 будет уничтожен! Когда вы вернетесь к Tab 1, фрагмент в Tab 1 будет создан снова.

Кроме того, я не вижу, что «notifyDataSetChanged ()» вызывается в фрагменте onViewCreated () IngredientsFragment. Я хочу, чтобы вы снова загружали данные из CursorAdapter.

Я советую не загружать все одновременно по соображениям производительности, но если вы хотите это сделать, я советую вам переопределить функцию getItem () на вашем FragmentStatePagerAdapter

Извините, я пишу этот образец на java, но когда copy-paste, который на Android Studio, это будет автоматически переводиться на язык Kotlin:

 private class MyDataViewPagerAdapter extends FragmentStatePagerAdapter { private MyDataViewPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int position) { switch (position) { case PAGE_ONE: return FragmentOne.newInstance(); case PAGE_TWO: return FragmentTwo.newInstance(); case PAGE_Three: default: return FragmentThree.newInstance(); } } @Override public CharSequence getPageTitle(int position) { switch (position) { case PAGE_ONE: return "PAGE_ONE"; case PAGE_TWO: return "PAGE_ONE"; case PAGE_Three: default: return "PAGE_ONE"; } } @Override public int getCount() { return TOTAL_PAGE_COUNT; } } 

внутри вашей деятельности:

используйте это, чтобы связать TabLyout и View pager:

  // set adapter mPager.setAdapter(mPagerAdapter); tabs.setupWithViewPager(mPager); 
Intereting Posts
Как скопировать список Завершенных исполнений с помощью RxJava? Обратные вызовы Android и повторное использование кода что делает (x..x) .map в kotlin android Интерфейсы Kotlin экспортируют в Javascript отсутствующие свойства Kotlin: обходной путь для no lateinit при использовании настраиваемого сеттера? Как использовать простое наследование для класса данных? Критики Котлина и неправильный вывод Как преобразовать цифру Char (0-9) в числовое значение? Как изменить стандартную оболочку Gradle и файл сборки в IntelliJ? Определение конструктора по умолчанию и вторичного конструктора в Котлине со свойствами правильное поведение сопрограмм? Ошибка: невозможно получить доступ к NotNull Spring REST, Kotin и примитивные параметры по умолчанию приводят к ошибке UNINITIALIZED_VARIABLE Переменная _longPressed должна быть инициализирована Как добавить расширение оператора как часть контекста конкретного класса без подкласса?