NullPointerException异常时,试图从另一个片段更新一个ListView [英] NullPointerException when trying to update a ListView from another Fragment

查看:187
本文介绍了NullPointerException异常时,试图从另一个片段更新一个ListView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个片段,QuickNoteFragment和HistoryFragment,这是一个NavigationDrawer的一部分(这是FragmentActivity它们绑定到)。在QuickNoteFragment我有一个按钮。当此按钮pressed,我想另一个项目添加到HistoryFragment ListView中。

I have two fragments, QuickNoteFragment and HistoryFragment, which are a part of a NavigationDrawer (this is the FragmentActivity they a bound to). In QuickNoteFragment I have a button. When this button is pressed, I would like another item added to the ListView in HistoryFragment.

我问这个问题:改变从另一个片段一个ListView的项目,并得到了过度用一个很好的解决方案。但我得到一个NullPointerException异常,当我这样做。我们有一个很长的太长了评论的对话,试图找到一个解决办法,但无济于事。所以,问题是:我该如何摆脱这种异常?这是我如何重现它

I asked this question: change the items in a ListView from another fragment and got a nice solution from srain. But I get a nullpointerexception, when I do this. We had a very long (too long) comment conversation to try and find a solution, but to no avail. So the question is: How do I get rid of this exception? This is how I reproduce it

打开应用程序 - >它会自动启动QuickNoteFragment。我preSS按钮 - 通过NavDrawer>我打开HistoryFragment(ViewPager的一部分)。我不明白的字符串数据敬酒。 - >我回去QuickNoteFragment - >我preSS按钮 - >强制每次我重复这个时候关闭

Open app -> It automatically starts QuickNoteFragment. I press the button -> I open HistoryFragment (part of ViewPager) via the NavDrawer. I do NOT get the toast with the string data. -> I go back to QuickNoteFragment -> I press the Button -> Force Close every time I repeat this.

这是 NavigationDrawer ,我用它来启动片段:

This is the NavigationDrawer that I use to start the fragments:

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class Navigation_Drawer extends FragmentActivity {

    public DrawerLayout mDrawerLayout; // Creates a DrawerLayout called_.
    public ListView mDrawerList;
    public ActionBarDrawerToggle mDrawerToggle;

    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    private String[] mNoterActivities; // This creates a string array called _.

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub

// Just setting up the navigation drawer

    } // End of onCreate

// Removed the menu


        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position,
                long id) {
            selectItem(position);
        }
    }

    private void selectItem(int position) { 

        FragmentManager fragmentManager = getSupportFragmentManager();

        if (position == 0) {
            Fragment qnfragment = new QuickNoteFragment(); 
            ((FragmentBase) qnfragment).setContext(this);
            Bundle args = new Bundle(); // Creates a bundle called args
            args.putInt(QuickNoteFragment.ARG_nOTERACTIVITY_NUMBER, position); 

            qnfragment.setArguments(args);

            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame, qnfragment).commit();



        } else if (position == 3) {
            Fragment pendViewPager = new PendViewPager(); // This is a ViewPager that includes HistoryFragment
            ((FragmentBase) pendViewPager).setContext(this);
            Bundle args = new Bundle();

            pendViewPager.setArguments(args);
            fragmentManager.beginTransaction()
                    .replace(R.id.content_frame, pendViewPager).commit();
        }

    // Update title etc
    }


    @Override
    protected void onPostCreate(Bundle savedInstanceState) { // Used for the NavDrawer toggle
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) { // Used for the NavDrawer toggle
        super.onConfigurationChanged(newConfig);
        // Pass any configuration change to the drawer toggles
        mDrawerToggle.onConfigurationChanged(newConfig);
    }

}

这是QuickNoteFragment:

This is QuickNoteFragment:

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.net.Uri;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.NotificationCompat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

public class QuickNoteFragment extends FragmentBase implements OnClickListener {

    public static final String ARG_nOTERACTIVITY_NUMBER = "noter_activity";

    Button b_create;
// removed other defining stuff

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.quicknote, container, false);
        int i = getArguments().getInt(ARG_nOTERACTIVITY_NUMBER);
        String noter_activity = getResources().getStringArray(
                R.array.noter_array)[i];
        FragmentManager fm = getFragmentManager();
        setRetainInstance(true);

        b_create = (Button) rootView.findViewById(R.id.qn_b_create);

        // Removed other stuff

        getActivity().setTitle(noter_activity);
        return rootView;
    }

    @Override
    public void onClick(View v) {

        // TODO Auto-generated method stub

        switch (v.getId()) {

        case R.id.qn_b_create:

                              String data = "String data";
                DataModel.getInstance().addItem(data);

            break;
        }
    }

@Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // TODO Auto-generated method stub
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle item selection

        }
    }

    public interface OnItemAddedHandler { // Srains code
        public void onItemAdded(Object data);
    }
}

这是HistoryFragment(记住它的一部分 ViewPager

This is HistoryFragment (Remember it is part of a ViewPager):

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.RiThBo.noter.QuickNoteFragment.OnItemAddedHandler;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
import android.widget.Toast;

public class HistoryFragment extends FragmentBase implements OnItemAddedHandler {

    ListView lv;
    List<Map<String, String>> planetsList = new ArrayList<Map<String, String>>();
    SimpleAdapter simpleAdpt;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View view = inflater.inflate(R.layout.history, container, false);
        initList();


        ListView lv = (ListView) view.findViewById(R.id.listView);
        simpleAdpt = new SimpleAdapter(getActivity(), planetsList,
                android.R.layout.simple_list_item_1, new String[] { "planet" },
                new int[] { android.R.id.text1 });

        lv.setAdapter(simpleAdpt);

        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {

            public void onItemClick(AdapterView<?> parentAdapter, View view,
                    int position, long id) {

                // We know the View is a TextView so we can cast it

                TextView clickedView = (TextView) view;

                Toast.makeText(
                        getActivity(),
                        "Item with id [" + id + "]  - Position [" + position
                                + "] - Planet [" + clickedView.getText() + "]",
                        Toast.LENGTH_SHORT).show();
            }

        });
        registerForContextMenu(lv);

        return view;

    }

    private void initList() {

        // We populate the planets

        planetsList.add(createPlanet("planet", "Mercury"));
        planetsList.add(createPlanet("planet", "Venus"));
        planetsList.add(createPlanet("planet", "Mars"));
        planetsList.add(createPlanet("planet", "Jupiter"));
        planetsList.add(createPlanet("planet", "Saturn"));
        planetsList.add(createPlanet("planet", "Uranus"));
        planetsList.add(createPlanet("planet", "Neptune"));

    }

    private HashMap<String, String> createPlanet(String key, String name) {

        HashMap<String, String> planet = new HashMap<String, String>();

        planet.put(key, name);

        return planet;

    }

    // We want to create a context Menu when the user long click on an item

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,

    ContextMenuInfo menuInfo) {

        super.onCreateContextMenu(menu, v, menuInfo);

        AdapterContextMenuInfo aInfo = (AdapterContextMenuInfo) menuInfo;

        // We know that each row in the adapter is a Map

        HashMap map = (HashMap) simpleAdpt.getItem(aInfo.position);

        menu.setHeaderTitle("Options for " + map.get("planet"));
        menu.add(1, 1, 1, "Details");
        menu.add(1, 2, 2, "Delete");

    }
     @Override
      public void onItemAdded(Object data) {
          // to add item
          String string = String.valueOf(data);
          Toast.makeText(getContext(), "Data: " + string, Toast.LENGTH_SHORT).show();
          planetsList.add(createPlanet("planet", string));
      }
      @Override
    public void onStart() {
          super.onStart();

          DataModel.getInstance().setOnItemAddedHandler(this);
      }
}

这是FragmentBase:

This is FragmentBase:

   import android.support.v4.app.Fragment;
    import android.support.v4.app.FragmentActivity;

      public class FragmentBase extends Fragment {

            private FragmentActivity mActivity; // I changed it to FragmentActivity because Activity was not working, and my `NavDrawer` is a FragmentActivity.

            public void setContext(FragmentActivity activity) {
                mActivity = mActivity;
            }

            public FragmentActivity getContext() {
                return mActivity;
            }
    }

这是DataModel的:

This is DataModel:

  import android.util.Log;
    import com.xxx.xxx.QuickNoteFragment.OnItemAddedHandler;

public class DataModel {

    private static DataModel instance;
    private static OnItemAddedHandler mOnItemAddHandler;

    public static DataModel getInstance() {
        if (null == instance) {
            instance = new DataModel();
        }
        return instance;
    }

    public void setOnItemAddedHandler(OnItemAddedHandler handler) {
        mOnItemAddHandler = handler;
    }

    public void addItem(Object data) {
        if (null != mOnItemAddHandler)
            mOnItemAddHandler.onItemAdded(data);
        else {
            Log.i("is context null?", "yes!");
        }  
    }
}

这是logcat的输出:

This is the logcat output:

07-20 10:20:12.325: E/AndroidRuntime(14977): FATAL EXCEPTION: main
07-20 10:20:12.325: E/AndroidRuntime(14977): java.lang.NullPointerException
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.widget.Toast.<init>(Toast.java:92)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.widget.Toast.makeText(Toast.java:238)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at com.RiThBo.noter.HistoryFragment.onItemAdded(HistoryFragment.java:126)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at com.RiThBo.noter.DataModel.addItem(DataModel.java:24)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at com.RiThBo.noter.QuickNoteFragment.onClick(QuickNoteFragment.java:103)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.view.View.performClick(View.java:4211)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.view.View$PerformClick.run(View.java:17362)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.os.Handler.handleCallback(Handler.java:725)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.os.Handler.dispatchMessage(Handler.java:92)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.os.Looper.loop(Looper.java:137)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at android.app.ActivityThread.main(ActivityThread.java:5233)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at java.lang.reflect.Method.invokeNative(Native Method)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at java.lang.reflect.Method.invoke(Method.java:511)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:562)
07-20 10:20:12.325: E/AndroidRuntime(14977):    at dalvik.system.NativeStart.main(Native Method)

感谢您

推荐答案

由于您想 HistoryFragment 继续保持活跃,你去了 QuickNoteFragment ,所以你不应该替换片段,如下面的code:

Because you want HistoryFragment keep active after you went to QuickNoteFragment, so you should not replace the fragment, like the code below:

fragmentManager.beginTransaction().replace(R.id.content_frame, qnfragment).commit();

我也为了让所有的碎片保持活跃修改 Navigation_Drawer

private FragmentBase mCurrentFragment;

private void selectItem(int position) {

    FragmentManager fragmentManager = getSupportFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
    String fragmentTag = String.valueOf(position);

    FragmentBase fragment = (FragmentBase) fragmentManager.findFragmentByTag(fragmentTag);
    if (null == fragment) {
        fragment = createFragmentByPosition(position);
    }
    if (null == fragment)
        return;

    if (fragment.isAdded()) {
        fragmentTransaction.show(fragment);
    } else {
        fragmentTransaction.add(R.id.content_frame, fragment, fragmentTag);
    }

    if (mCurrentFragment != null) {
        fragmentTransaction.hide(mCurrentFragment);
    }
    mCurrentFragment = fragment;
    fragmentTransaction.commitAllowingStateLoss();

    mDrawerList.setItemChecked(position, true);
    setTitle(mNoterActivities[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

private FragmentBase createFragmentByPosition(int position) {
    FragmentBase fragment = null;
    if (position == 0) {
        fragment = new QuickNoteFragment();
        Bundle args = new Bundle();
        args.putInt(QuickNoteFragment.ARG_nOTERACTIVITY_NUMBER, position);
        fragment.setArguments(args);

    } else if (position == 1) {
        fragment = new PendViewPager();
        Bundle args = new Bundle();
        fragment.setArguments(args);
    }
    return fragment;
}

然后在 onItemAdded HistoryFragment ,仍然使用 getActivity()

@Override
public void onItemAdded(Object data) {
    // to add item
    String string = String.valueOf(data);
    Toast.makeText(getActivity(), "Data: " + string, Toast.LENGTH_SHORT).show();
    planetsList.add(createPlanet("planet", string));
}

FragmentBase 删除低于code:

private FragmentActivity mActivity; // I changed it to FragmentActivity
                                    // because Activity was not working, and
                                    // my `NavDrawer` is a FragmentActivity.

public void setContext(FragmentActivity activity) {
    mActivity = mActivity;
}

public FragmentActivity getContext() {
    return mActivity;
}

如果您没有添加其他内容到 FragmentBase ,这将是:

If you did not add other content into FragmentBase, it will be:

 class FragmentBase extends Fragment {

 }

是的,它是空的,但我建议保持它。

Yes, it is empty, but I suggest to keep it.

最后,如果 HistoryFragment 为背景,可以通过系统分离时应用回到后台。所以从注销自的DataModel 时分离:

At last, If HistoryFragment is at background, it may be detached by system when app go back to background. so unregister self from DataModel when detach:

@Override
public void onDetach() {
    super.onDetach();
    DataModel.getInstance().setOnItemAddedHandler(null);
} 

UPDATE1

@Override
public void onItemAdded(Object data) {
    // to add item
    String string = String.valueOf(data);
    planetsList.add(createPlanet("planet", string));
    simpleAdpt.notifyDataSetChanged();
}

这篇关于NullPointerException异常时,试图从另一个片段更新一个ListView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆