【问题标题】:android - Pass data from Activity to Fragment in ViewPagerandroid - 将数据从 Activity 传递到 ViewPager 中的 Fragment
【发布时间】:2018-02-13 11:12:31
【问题描述】:

我有一个简单的 Activity,其中包含 TabLayout、ViewPager 和 2 个片段。这是我的活动:

public class ManagementCompanyOverviewActivity extends BaseActivity implements ManagementCompanyOverviewView {

    private ManagementCompanyVPAdapter mVPAdapter;
    private TabLayout mTLContent;
    private ViewPager mVPContent;

    @InjectPresenter
    ManagementCompanyPresenter mPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_management_company);

        mVPAdapter = new ManagementCompanyVPAdapter(getSupportFragmentManager());

        mTLContent = (TabLayout) findViewById(R.id.tl_company_content);

        mVPContent = (ViewPager) findViewById(R.id.vp_company_content);
        mVPContent.setAdapter(mVPAdapter);
        mTLContent.setupWithViewPager(mVPContent);
    }

    @Override
    public void onAboutCompanyInfoReceivedFromServer(AboutCompanyViewModel model) {

    }

Activity 有一个 Presenter(我正在使用 Moxy),Presenter 发送请求,获取答案,创建 JavaObject(视图模型)并使用 getViewState() 将此模型传递给 Activity。我需要将此模型从 Activity 传递给我的一个 Fragment。

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

    View view = inflater.inflate(R.layout.fragment_about_company, container, false);

    mTVName = (TextView) view.findViewById(R.id.tv_company_name);
    mTVDirector = (TextView) view.findViewById(R.id.tv_company_director);
    mTVWebsite = (TextView) view.findViewById(R.id.tv_company_website);
    mTVEmail = (TextView) view.findViewById(R.id.tv_company_email);
    mTVPhone = (TextView) view.findViewById(R.id.tv_company_phone);
    mTVSchedule = (TextView) view.findViewById(R.id.tv_company_schedule);
    mTVAddress = (TextView) view.findViewById(R.id.tv_company_address);

    return view;
}

这个片段有一些 TextViews 来显示来自我的模型的信息。如何通过这个模型?如果我知道正确,我应该创建一个侦听器,但是如何?我不完全了解如何使用它们。

【问题讨论】:

    标签: android android-viewpager fragment listener


    【解决方案1】:

    好的,我做到了。

    1 步:我在我的 Activity 中创建了公共接口并为其设置:

    private OnAboutDataReceivedListener mAboutDataListener;
    
    public interface OnAboutDataReceivedListener {
            void onDataReceived(AboutCompanyViewModel model);
        }
    
    public void setAboutDataListener(OnAboutDataReceivedListener listener) {
        this.mAboutDataListener = listener;
    }
    

    第 2 步:我在 Fragment 中实现了这个接口并设置了监听器:

    public class AboutCompanyFragment extends BaseFragment implements ManagementCompanyOverviewActivity.OnAboutDataReceivedListener
    
        @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
    
                mActivity = (ManagementCompanyOverviewActivity) getActivity();
                mActivity.setAboutDataListener(this);
            }
    

    第三步:我重写了接口的方法:

    @Override
        public void onDataReceived(AboutCompanyViewModel model) {
            mPBName.setVisibility(View.INVISIBLE);
            mPBDirector.setVisibility(View.INVISIBLE);
            mPBWebsite.setVisibility(View.INVISIBLE);
            mPBEmail.setVisibility(View.INVISIBLE);
            mPBPhone.setVisibility(View.INVISIBLE);
            mPBSchedule.setVisibility(View.INVISIBLE);
            mPBAddress.setVisibility(View.INVISIBLE);
    
            mTVName.setVisibility(View.VISIBLE);
            mTVDirector.setVisibility(View.VISIBLE);
            mTVWebsite.setVisibility(View.VISIBLE);
            mTVEmail.setVisibility(View.VISIBLE);
            mTVPhone.setVisibility(View.VISIBLE);
            mTVSchedule.setVisibility(View.VISIBLE);
            mTVAddress.setVisibility(View.VISIBLE);
    
            mTVName.setText(model.getCompanyName());
            mTVDirector.setText(model.getDirectorName());
            mTVWebsite.setText(model.getWebsite());
            mTVEmail.setText(model.getEmail());
            mTVPhone.setText(model.getPhone());
            mTVSchedule.setText(model.getWorkTime());
            mTVAddress.setText(model.getAddress());
        }
    

    就是这样。

    【讨论】:

    • 非常感谢。你节省了我的时间。
    • 如何从活动中分配 AboutCompanyViewModel?
    • @MasterpieceMasIcang 你只需调用你的接口方法并传递它。
    • @Den 你能告诉我如何通过示例从活动中设置数据
    • 片段被替换或销毁时会中断吗?
    【解决方案2】:

    试试这个 活动中

    public String sendData() {
            return YOUR_STRING;
        }
    

    在片段中

    YOUR_ACTIVITY activity = (YOUR_ACTIVITY) getActivity();
    String getData = activity.SendData();
    

    【讨论】:

    • 不,不行。数据来自服务器,可以在 3-5 秒内收到。当我的 Activity 收到此数据时,将调用方法 public void onAboutCompanyInfoReceivedFromServer(AboutCompanyViewModel model)。
    • Activity 应该在数据准备好时将数据发送到 Fragment。我不能使用 getter。
    • 您可以在收到数据时尝试 setupViewPager,我确实喜欢在我的应用中这样做
    • 你能发布一些示例代码吗?只需编辑您的第一个答案 :)
    • 我不知道你从哪里获取数据。我正在使用 AsyncTask,当任务完成时,我调用 setupViewPager。只需放 mTLContent.setupWithViewPager(mVPContent);获取数据响应的方法
    【解决方案3】:

    您可以在 Fragment 中使用 newInstance 方法:

    public static MyFragment newInstance(String parameter) {
    
            Bundle args = new Bundle();
            args.putString("parameter", parameter);
            SfCategoryFragment fragment = new SfCategoryFragment();
            fragment.setArguments(args);
            return fragment;
        }
    
        @Override
        public void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            if (getArguments() != null) {
                parameter = getArguments().getString("parameter");
            }
        }
    

    在你的活动中:

    MyFragment.newInstance("yourParam");代替new MyFragment()

    【讨论】:

    • 谢谢。它适用于我的情况,节省了我很多时间!
    【解决方案4】:

    您还可以在适配器的构造函数中获取要在片段中显示的数据并在返回新片段之前设置参数

    public class ViewPagerAdapter extends FragmentStatePagerAdapter {
    private Weather weather;
    
    ViewPagerAdapter(FragmentManager fm, Weather weather) {
        super(fm);
        this.weather = weather;
    }
    
    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                Bundle bundle = new Bundle();
                WeatherFragment weatherFragment = new WeatherFragment();
                bundle.putParcelable("weather", weather);
                weatherFragment.setArguments(bundle);
                return weatherFragment;
            case 1:
                return new PoemFragment();
            default:
                return new EmptyFragment();
        }
    }
    

    【讨论】:

    • 不,我的片段已经在运行,我不想重新初始化它
    • 嗨,这个问题的新解决方案是。如果您使用的是 MVVM,则使用共享的 viewModel。谢谢!
    【解决方案5】:

    来自 Activity 或 ViewPager

    Bundle bundle = new Bundle();
    bundle.putParcelable(Keys.KEY_ITEM, cardResult);
    CardItemFragment cardItemFragment = new CardItemFragment();
    cardItemFragment.setArguments(bundle);
    

    从片段

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
         getBundle();
    }
    
    
    private void getBundle() {
        bundle = getArguments();
        if (null != bundle) {
            if (bundle.containsKey(Keys.KEY_ITEM)) {
                cardResult = bundle.getParcelable(Keys.KEY_ITEM);
            }
        }
    }
    

    【讨论】:

      【解决方案6】:

      片段

      class SampleFragment : Fragment(), BaseFragmentInteraction {
          override fun updateFragmentData(data: String) {
              Toast.makeText(activity!!, data, Toast.LENGTH_SHORT).show()
          }
      }
      

      界面

      interface BaseFragmentInteraction {
          fun updateFragmentData(data: String)
      }
      

      活动:

      view_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {
      
              override fun onPageSelected(position: Int) {
                  val fragmentItem = (view_pager.adapter as FragmentPagerAdapter).getItem(view_pager.currentItem)
                  (fragmentItem as BaseFragmentInteraction).updateFragmentData("SomeData")
              }
      
              override fun onPageScrollStateChanged(state: Int) {}
      
              override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
          })
      

      updateFragmetData 方法将在当前选定的 viewpager 项目片段中调用。您还可以向updateFragmetData 添加标签参数,以便确保调用正确的片段实例。如果需要,您可以在updateFragmetData 实现中调用isVisible 以确保片段可见。

      【讨论】:

        【解决方案7】:

        我找到了一种将数据直接传递给片段或片段适配器的新方法

        首先你创建一个获取数据的getter方法假设你想获取用户名 你在活动中创建一个方法

        public String getUsername(){
        return username;
        }
        

        然后你从片段以及像这样的片段适配器调用这个方法

        片段

        (MainActivity) getActivity()).getUsername()
        

        适配器

        (MainActivity) context).getUsername()
        
        

        这种方式还可以帮助您减少对数据库的请求数

        【讨论】:

        • 如果你的 Fragment 被用于另一个 Activity 怎么办?你总是应该使用接口来重用你的代码。
        • 您是 100% 正确的,但我们正在讨论从活动到片段的数据传递,如果您需要其他活动中未处于运行状态的数据,那么您必须使用接口
        • 无论如何,在我原来的帖子中,活动从互联网接收一些数据,并且该活动应该将这些数据发送到片段,在这种情况下,getter 将无济于事。
        猜你喜欢
        • 1970-01-01
        • 2018-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-07-26
        • 2021-01-07
        相关资源
        最近更新 更多