【问题标题】:Running an AsynTask in a GridFragment is causing a null pointer on rotation在网格片段中运行异步任务导致旋转时出现空指针
【发布时间】:2013-11-13 16:36:24
【问题描述】:

我有一个有 5 个 Fragment 的 FragmentActivity

我的第二个片段是一个显示许多图像的网格视图。

那个 GridFragment 正在启动一个带有回调的 AsyncTask 以获取图像的数组列表。

然后它使用以下作为参数(侦听器、上下文、数组列表)设置适配器上下文是 getActivity()

当适配器启动时,它会尝试执行 LayoutInflater.from(Context);

这就是我得到空指针的地方。如果异步任务完成,它不会崩溃。但是我在异步任务运行时旋转它崩溃了。

有没有办法解决这个问题?

片段

public class IconsFrag extends GridFragmentIcons implements AdapterIcons.AdapterListener {

    AsyncTaskIconsAll aTask;
    Button button;
    final String TAG = "IconsFrag";
    private ArrayList<Integer> mThumbs;
    private final String KEY_LIST_DATA = "icons_cache";
    private final String KEY_LIST_POSITION = "icons_position";
    private int mPosition = -1;
    private AdapterIcons mAdapter;

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        Log.i(TAG, "onActivityCreated");
        super.onCreate(savedInstanceState);

        if (savedInstanceState == null){
            Log.i(TAG, "savedInstanceState null");
            aTask = new AsyncTaskIconsAll();
            aTask.updateActivity(this, getActivity(), new AsyncTaskIconsAll.Callback() {
                @Override
                public void onData(ArrayList<Integer> data) {
                    mThumbs = data;

                    mAdapter = new AdapterIcons(IconsFrag.this, getActivity(), mThumbs);
                    getGridView().setNumColumns(getResources().getInteger(R.integer.column_count_icon));
                    setGridAdapter(mAdapter);
                    getGridView().setOnItemClickListener(null);
                }
            });
            aTask.execute();
        }

异步任务

public class AsyncTaskIconsAll extends AsyncTask<Void, Integer, ArrayList<Integer>> {

    private Activity mContext;
    private Fragment mFragment;
    private ArrayList<Integer> mThumbs;
    final String TAG = "AsyncTaskIconsAll";
    Callback mCallback;

    public static interface Callback{
        public void onData(ArrayList<Integer> data);
    }

    public void updateActivity(Fragment f, Activity a, final Callback c) {
        Log.i(TAG, "updateActivity");
        mContext = a;
        mFragment = f;
        mCallback = c;
        if(mThumbs != null)
            Log.i(TAG, "Callback not null");
            mCallback.onData(mThumbs);
    }

    @Override
    protected void onPreExecute() {

    }

    @Override
    protected ArrayList<Integer> doInBackground(Void... unused){
        Log.i(TAG, "doInBackground");
        mThumbs = new ArrayList<Integer>();
        final String[] extras = mContext.getResources().getStringArray(R.array.icon_pack);
            for (String extra : extras) {
                String uri = "drawable/" + extra;
                int res = mContext.getResources().getIdentifier(uri, null, mContext.getPackageName());
                if (res != 0) {
                    mThumbs.add(res);
                }
            }
        return mThumbs;
    }

    protected void onProgressUpdate(Integer... progress) {

    }

    @Override
    protected void onPostExecute(ArrayList<Integer> icons) {
        Log.i(TAG, "onPostExecute");
        mThumbs = icons;
        mCallback.onData(mThumbs);
        ProgressBar mProgess = (ProgressBar) mFragment.getView().findViewById(R.id.pending);
        mProgess.setVisibility(mFragment.getView().GONE);
    }
}

适配器

public class AdapterIcons extends BaseAdapter implements SpinnerAdapter {

    private final String TAG = "AdapterIcons";
    private AdapterListener mListener;
    private ArrayList<?> mData;
    private final LayoutInflater mInflater;

    public AdapterIcons(AdapterListener listener, Activity activity) {
        this.mData = new ArrayList<Object>();
        this.mInflater = LayoutInflater.from(activity);
        this.mListener = listener;
    }

    public AdapterIcons(AdapterListener listener, Context Context, ArrayList<?> data) {
        this.mData = (data == null) ? new ArrayList<Object>() : data;
        this.mInflater = LayoutInflater.from(Context);
        this.mListener = listener;
    }

    public ArrayList<?> getData () {
        return this.mData;
    }

    public void setData (ArrayList<?> data) {
        this.mData = data;
    }

    public void clearData () {
        this.mData.clear();
    }

    public static abstract interface AdapterListener
    {
        public abstract View getView(int paramInt, View paramView, ViewGroup paramViewGroup);
    }

    public Intent.ShortcutIconResource getResource(int position){
        Icons icons= new Icons();
        ArrayList<Integer> list = (ArrayList<Integer>) mData;
        return Intent.ShortcutIconResource.fromContext(icons.getBaseContext(), list.get(position));
    }

    @Override
    public int getCount () {
        if (mData == null)
            Log.d(TAG, "getCount() Data Set Is Null");
        return (mData != null) ? mData.size() : 0;
    }

    @Override
    public Object getItem (int position) {
        if (mData == null)
            Log.d(TAG, "getItem(int position) Data Set Is Null");
        return (mData != null) ? mData.get(position) : null;
    }

    @Override
    public long getItemId (int position) {
        if (mData == null)
            Log.d(TAG, "getItemId(int position) Data Set Is Null");
        return (mData != null) ? position : 0;
    }

    @Override
    public View getView (int position, View convertView, ViewGroup parent) {
        return (mListener == null) ? new LinearLayout(mInflater.getContext()) : this.mListener.getView(position, convertView, parent);
    }

    @Override
    public View getDropDownView (int position, View convertView, ViewGroup parent) {
        return (mListener == null) ? new LinearLayout(mInflater.getContext()) : this.mListener.getView(position, convertView, parent);
    }

}

【问题讨论】:

    标签: android


    【解决方案1】:

    看看这个答案。这几乎是同样的问题。您需要处理默认情况下更改活动状态的方向更改(如果您不覆盖)。

    https://stackoverflow.com/a/7618739/1080954

    【讨论】:

      【解决方案2】:

      所以在您的onPostExecute() 中,您尝试将项目添加到(暂时)销毁的活动中。在处理上下文之前检查您的getActivity() == null。比如:

      public void onPostExecute(){
      
          if(getActivity() == null){
              // activity is destroyed... skip
              return;
          }
      
          // proceed like normal
      
      }
      

      这是我在没有代码的情况下能做的最好的事情。祝你好运

      【讨论】:

        【解决方案3】:

        你有没有注意到你应该在这里使用方括号 {},否则mCallback.onData(mThumbs) 将始终被调用:

        if(mThumbs != null){
                Log.i(TAG, "Callback not null");
                mCallback.onData(mThumbs);
        }
        

        此外,当您创建 asyncTask 时,您在 asyncTask updateActivity() 方法中传递了 fragmentactivity,但是当您旋转设备时它们将为空,活动将被重新创建,所以当您在 asyncTask doInBackground()onPostExecute() 中使用它们,你必须先检查它们是否不为空,否则你最终可能会出现 NullPointerException。

        【讨论】:

        • @Bignadad 响应已更改
        • 感谢您的提示,这将在已创建 mthumbs 时有所帮助。但是对于我有 mthumbs 的问题是空的。如果用户在 mthumbs 构建时旋转设备,则会崩溃
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-10-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-09-24
        相关资源
        最近更新 更多