android - 设备旋转导致的 ViewPager 和 LoaderManager 错误

标签 android android-viewpager android-loadermanager

我使用一个包含 3 个 fragment 的 ViewPager。使用 LoaderManager 额外加载每个 fragment 数据。我实现了自己的加载程序,但如果我旋转设备并且实际选择了加载程序选项卡,则寻呼机和加载程序的组合会在 NullPointerException 中运行。这是我的日志。

java.lang.NullPointerException android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:960) android.support.v4.app.FragmentManagerImpl.performPendingDeferredStart(FragmentManager.java:768) android.support.v4.app.FragmentManagerImpl.startPendingDeferredFragments(FragmentManager.java:1104) android.support.v4.app.LoaderManagerImpl$LoaderInfo.onLoadComplete(LoaderManager.java:410) android.support.v4.content.Loader.deliverResult(Loader.java:103) com.android.droidfridge.loader.FridgeLoader.deliverResult(FridgeLoader.java:144) com.android.droidfridge.loader.FridgeLoader.deliverResult(FridgeLoader.java:1) android.support.v4.content.AsyncTaskLoader.dispatchOnLoadComplete(AsyncTaskLoader.java:221) android.support.v4.content.AsyncTaskLoader$LoadTask.onPostExecute(AsyncTaskLoader.java:61) android.support.v4.content.ModernAsyncTask.finish(ModernAsyncTask.java:461) android.support.v4.content.ModernAsyncTask.access$500(ModernAsyncTask.java:47) android.support.v4.content.ModernAsyncTask$InternalHandler.handleMessage(ModernAsyncTask.java:474)

这是我完整的加载程序代码:

package com.android.droidfridge.loader;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.TreeSet;

import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;
import android.util.Log;

import com.android.droidfridge.adapters.FridgeEntryItem;
import com.android.droidfridge.adapters.Item;
import com.android.droidfridge.adapters.SectionItem;
import com.android.droidfridge.database.DatabaseHelper;
import com.android.droidfridge.database.Items;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.stmt.QueryBuilder;

public class FridgeLoader extends AsyncTaskLoader<List<Item>>
{
    private final static String TAG = "FridgeLoader";

    private DatabaseHelper db = null;
    private List<Item> item;

    private ItemComparator option;
    private boolean ascending;

    public FridgeLoader( Context context, DatabaseHelper db, ItemComparator option, boolean ascending )
    {
        super( context );
        this.db = db;
        this.option = option;
        this.ascending = ascending;
    }

    @Override
    public List<Item> loadInBackground()
    {
        Log.i( TAG, "Started loadInBackground." );

        ArrayList<Item> result = new ArrayList<Item>();
        TreeSet<String> sections = new TreeSet<String>();

        try
        {
            // search for all items
            Dao<Items, Integer> dao = db.getItemsDao();
            QueryBuilder<Items, Integer> builder = dao.queryBuilder();
            builder.where().gt( Items.ACTUAL_AMOUNT_COLUMN, 0 );
            List<Items> data = dao.query( builder.prepare() );

            // sort items list
            data = sortData( data );

            // create list view items
            for( Items item : data )
            {
                // add Category
                if( !sections.contains( item.getCategory().getName() ) )
                {
                    sections.add( item.getCategory().getName() );
                    result.add( new SectionItem( item.getCategory() ) );
                }

                // add Item
                result.add( new FridgeEntryItem( item ) );
            }
        }
        catch( SQLException e )
        {
            Log.e( TAG, "loadInBackground: " + e.getMessage() );
        }

        return result;
    }

    private List<Items> sortData( List<Items> data )
    {
                //...
        return sortedResult;
    }

    @Override
    public void deliverResult( List<Item> data )
    {
        if( isReset() )
        {
            if( data != null )
            {
                onReleaseResources( data );
            }
        }

        List<Item> oldData = data;
        item = data;

        if( isStarted() )
        {
            super.deliverResult( data );
        }

        if( oldData != null )
        {
            onReleaseResources( oldData );
        }
    }

    @Override
    protected void onStartLoading()
    {
        Log.d( TAG, "onStartLoading()" );

        if( item != null )
        {
            deliverResult( item );
        }

        if( takeContentChanged() || item == null )
        {
            forceLoad();
        }
    }

    @Override
    protected void onStopLoading()
    {
        Log.d( TAG, "onStopLoading()" );

        cancelLoad();
    }

    @Override
    public void onCanceled( List<Item> data )
    {
        Log.d( TAG, "onCanceled()" );
        super.onCanceled( data );
        onReleaseResources( data );
    }

    @Override
    protected void onReset()
    {
        Log.d( TAG, "onReset()" );
        super.onReset();

        onStopLoading();

        if( item != null )
        {
            onReleaseResources( item );
            item = null;
        }
    }

    private void onReleaseResources( List<Item> data )
    {
    }
}

最佳答案

我找到了解决问题的方法。它位于 fragment 事务中。重要的是:

setRetainInstance( true );

这一行来 self 的 fragment ,它从上面使用了这个加载器。它在他的构造函数中。

关于android - 设备旋转导致的 ViewPager 和 LoaderManager 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11466727/

相关文章:

java - 使用 11 之前的 Loader em API 版本

android - 调用 LoaderCallbacks.onLoadFinished() 的规则是什么?

android - 使用 LoaderManager 加载依赖查询的首选方法

android - Android Studio-Gradle list 文件路径

android - 任务 ':app:kaptDebugKotlin' 执行失败。 > 执行 org.jetbrains.kotlin.gradle.internal.KaptExecution 时发生故障

android - 如何删除android中的标题栏?

android - 您可以将分页库和 PagedList 与 ViewPager 一起使用吗?

android-viewpager - ViewPager2 迁移后出现无效 ID 0x00000001 错误

java - 制作按钮下方的布局

Android:从 TextView 复制到剪贴板选定的文本