【问题标题】:Issue when getting reference to fragment inside ViewPager from activity从活动中获取对 ViewPager 内片段的引用时出现问题
【发布时间】:2016-07-24 10:58:12
【问题描述】:

我需要在 Fragment 中将文本值设置为 EditText。在我的活动中,ViewPager 中添加了 5 个这样的片段。为了做到这一点,我需要参考ViewPager 中的片段。我用ViewPager下面的适配器。

public class MessageViewPageAdapter extends FragmentPagerAdapter {

    private List<Fragment> pages;
    private HashMap<Integer,Fragment> fragmentReference;

    public MessageViewPageAdapter(FragmentManager fm, List<Fragment> pages) {
        super(fm);
        this.pages = pages;
        fragmentReference = new HashMap<>();
    }

    @Override
    public Fragment getItem(int position) {
        Fragment fragment = pages.get(position);
        fragmentReference.put(position,fragment);
        return pages.get(position);
    }

    @Override
    public int getCount() {
        return pages.size();
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        super.destroyItem(container, position, object);
        fragmentReference.remove(position);
    }

    public Fragment getFragment(int key) {
        return fragmentReference.get(key);
    }
}

如您所见,fragmentReference HashMap 用于将所有片段存储在ViewPager 中。 getFragment(int key) 方法用于从该哈希映射中获取片段。这就是我的活动的样子。

public class MainActivity extends AppCompatActivity {

    private ViewPager messageViewPage;
    private Fragment message1;
    private Fragment message2;
    private Fragment message3;
    private Fragment message4;
    private Fragment message5;

    private List<Fragment> fragments = new ArrayList<>();
    private MessageViewPageAdapter messageViewPageAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        messageViewPage = (ViewPager) findViewById(R.id.message_viewPage);

        message1 = new Message1();
        message2 = new Message2();
        message3 = new Message3();
        message4 = new Message4();
        message5 = new Message5();
        fragments.add(message1);
        fragments.add(message2);
        fragments.add(message3);
        fragments.add(message4);
        fragments.add(message5);

        messageViewPageAdapter = new MessageViewPageAdapter(getSupportFragmentManager(), fragments);
        messageViewPage.setAdapter(messageViewPageAdapter);
        messageViewPage.setOffscreenPageLimit(5);

        Message1 message1fragment = (Message1) messageViewPageAdapter.getFragment(0);
        Message2 message2fragment = (Message2) messageViewPageAdapter.getFragment(1);
        Message3 message3fragment = (Message3) messageViewPageAdapter.getFragment(2);
        Message4 message4fragment = (Message4) messageViewPageAdapter.getFragment(3);
        Message5 message5fragment = (Message5) messageViewPageAdapter.getFragment(4);


    } 

但我得到所有 5 个片段的空值 (message1fragment,message2fragment,message3fragment,message4fragment,message5fragment)

但是,当我将相同的代码放入单击按钮时,如下所示,它工作正常。

button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Message1 message1fragment = (Message1) messageViewPageAdapter.getFragment(0);
                Message2 message2fragment = (Message2) messageViewPageAdapter.getFragment(1);
                Message3 message3fragment = (Message3) messageViewPageAdapter.getFragment(2);
                Message4 message4fragment = (Message4) messageViewPageAdapter.getFragment(3);
                Message5 message5fragment = (Message5) messageViewPageAdapter.getFragment(4);
            }
        });

我做错了什么?我什至尝试在 onStart()onResume() 方法中放置相同的代码,但结果相同。这个ViewPager 中的每个片段都有一个名为setMessage(String message) 的方法,我打算使用该方法将文本设置为该片段中的EditText。我需要在活动开始时这样做。

这就是我的消息片段的样子。

public class Message1 extends Fragment {

    private EditText message1;

    public Message1() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View inflate = inflater.inflate(R.layout.fragment_message1, container, false);
        message1 = (EditText) inflate.findViewById(R.id.message_1);
        return inflate;
    }

    public String getMessageOneText(){
        return String.valueOf(message1.getText());
    }

    public void setErrorMessage(){
        message1.setError("Message 1 can not be empty");
    }

    public void setMessage(String message){
        message1.setText(message);
    }

【问题讨论】:

    标签: android android-studio android-fragments android-viewpager


    【解决方案1】:

    在 onCreate 内部,ViewPager 尚未完全初始化,因此不会调用 getItem(...),因此您的 getFragment(...) 实现将返回 null。

    我建议将 getFragment 替换为:

    public Fragment getFragment(int key) {
        return pages.get(key);
    }
    

    并删除 fragmentReference,因为它似乎是多余的。

    【讨论】:

    • 通过使用您的更改,我能够获得我想要的片段。当我在片段中调用setMessage(String message) 时,给了我一个空点异常,说message1 是空的。所以我在 `onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState)' 方法上放置一个断点来查看它是否被调用。在发生空点异常之前没有到达断点。
    • 很可能该片段尚未附加到活动中。您需要将文本存储在片段的实例变量中,并将其存储在 onCreateView 中或之后的 EditText 中(甚至可能在 onResume 中)。不要忘记根据需要通过 savedInstanceState 包管理此值的保存和恢复。
    • 我无法做到从 SQLight 获取文本是动态的。 :(
    • 那么在fragment第一次显示的时候获取呢?您似乎确实希望在创建时复制它。如果您想要定期更新,那么如果文本字段不存在,则在本地变量中停止,否则设置文本
    • 底线:当文本编辑字段没有被实例化时,你不能设置它。要么稍后设置,要么保存在本地,直到创建 textview。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多