如何从FragmentDialog更新自定义RecyclerView?

时间:2016-04-07 13:19:20

标签: java android android-fragments android-recyclerview

我有一个片段为frag2的活动A.在片段内部,我有一个RecyclerView和Adapter来显示自定义类对象的列表。以编程方式处理向适配器添加对象。我在TwoFragment中有一个按钮,可以打开FragmentDialog。我想通过确认这个对话框向我的适配器添加一个对象,但是当从FragmentDialog调用时,似乎适配器为null。

同一个适配器不为null,如果我从片段OnClick调用它,它就可以工作。

此外,只有在屏幕旋转后适配器才为空,它在旋转之前工作正常。

为了在两个片段之间进行通信,我在活动A中实现了一个通信器类。

活动A

public void respond(String type) {
        frag2.addSupport(type);
    }

frag2

public RecyclerView rv;
public ArrayList<support> supports;
public myAdapter adapter;

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        supports = new ArrayList<>();
        adapter = new myAdapter(supports);
    }

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View layout = inflater.inflate( R.layout.fragment_two, container, false);
        layout.setId(R.id.frag2);


        if (savedInstanceState!=null)
        {
             supports = savedInstanceState.getParcelableArrayList("supports"); 
        }

        rv = (RecyclerView) layout.findViewById(R.id.rv);
        adapter = new myAdapter(supports);
        rv.setAdapter(myAdapter);
        rv.setLayoutManager(new LinearLayoutManager(getActivity()));
        rv.setItemAnimator(new DefaultItemAnimator());

@Override
    public void onClick(View v) {
        int id = v.getId();
        switch (id){
            case R.id.button1:
                addSupport(type); // THIS WORKS ALWAYS, even after screen rotate
                break;

            case R.id.button2:
                showDialog(); 
                break;
        }

    }

public void showDialog(){

        FragmentManager manager = getFragmentManager();
        myDialog dialog = new myDialog();
        dialog.show(manager, "dialog");
    }

public void addSupport(String type){

    adapter.addItem(new support(type));  // this line gives null pointer on adapter, but only if called after screen rotate and only if called from the dialog
            }

对话框

communicator comm;

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {


        View view = inflater.inflate(R.layout.dialog, null);
        comm = (myCommunicator) getActivity();
        create = (Button) view.findViewById(R.id.button_ok);
        create.setOnClickListener(this);

        return view;
    }



@Override
    public void onClick(View v) {

        if(v.getId()==R.id.button_ok)
        {
            // some controls to set type
            comm.respond(type)
            dismiss();
        }
        else {

            dismiss();
        }

myAdapter

public class myAdapter extends RecyclerView.Adapter<myAdapter.VH> {
    private LayoutInflater inflater;
    private ArrayList<support> data = new ArrayList<>();

// settings for viewholder

public myAdapter (ArrayList<support> data)
    {
        this.data=data;
    }

    public void addItem(support dataObj) {

        data.add(dataObj);
        notifyItemInserted(data.size());
    }

}

logcat的

FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'myAdapter.addItem(myObject)' on a null object reference

我希望没有错误,我缩短了代码以便更好地理解。请记住,如果我从不旋转屏幕,一切正常。

我是Android的初学者,现在我已经坚持了好几天了。请帮忙。

1 个答案:

答案 0 :(得分:0)

要理解这个问题,就像你说的那样:

  

..如果我从不旋转屏幕,一切正常

首先要了解旋转时会发生什么,这是来自Android Developer website

的引用
  

警告:每次用户旋转屏幕时,您的活动都将被销毁并重新创建。当屏幕更改方向时,系统会破坏并重新创建前台活动,因为屏幕配置已更改,您的活动可能需要加载其他资源(例如布局)。

好的,现在要了解错误:

FATAL EXCEPTION: main
java.lang.NullPointerException: Attempt to invoke virtual method 'myAdapter.addItem(myObject)' on a null object reference

基本上,在您的dialog课程中,您通过声明:

创建了强依赖性

comm = (myCommunicator) getActivity();

因为comm引用了旋转时销毁的对象,因此NullPointerException

为了进一步了解运行时更改,例如方向更改,我建议您浏览Handling Runtime Changes

更新

  

感谢您的回答,您会推荐什么而不是comm =(myCommunicator)getActivity(); ?

解决方案分为三部分:

  1. 确保onCreate的{​​{1}}具有以下内容:
  2. Activity A
    1. @Override public void onCreate(Bundle savedInstanceState) { ...... // find the retained fragment on activity restarts FragmentManager fm = getFragmentManager(); frag2 = (Frag2) fm.findFragmentByTag(“frag2”); // create frag2 only for the first time if (frag2 == null) { // add the fragment frag2 = new Frag2(); fm.beginTransaction().add(frag2 , “frag2”).commit(); } ...... } 添加到setRetainInstance(true)的{​​{1}}。

    2. 删除隐式引用,即onCreate,并为frag2实现更松散耦合的内容。

    3. <强>对话框

      comm = (myCommunicator) getActivity();

      这允许您在dialog(或任何其他类别)中执行以下操作:

      <强> frag2

      
      
          public interface Communicator {
      
              void respond(String type);
          }
      
          Communicator comm;
      
          ....
      
          public void addCommunicator(Communicator communicator) {
      
              comm = communicator;
          }
      
          public void removeCommunicator() {
      
              comm = null;
          }
      
          @Override
          public void onClick(View v) {
              if((v.getId()==R.id.button_ok) && (comm!=null))
              {
                  // some controls to set type
                  comm.respond(type);
              }
              // Regardless of what button is pressed, the dialog will dismiss
              dismiss();
          }