草庐IT

Android:在 viewpager fragment 之间传递数据的最佳方法

coder 2023-12-01 原文

我在 ViewPager Activity 中有 3 个 fragment 。所有 3 个 fragment 都有输入字段。在这里,我试图将前两个 fragment 数据传递给第三个 fragment 。我在这里读了几篇文章,其中大多数建议使用接口(interface)(即通过父 Activity 传递数据) 我也通过了这个链接 http://developer.android.com/training/basics/fragments/communicating.html

接口(interface):当我们通过某些用户事件发送数据时,使用接口(interface)是一种很好的方法。在这里,我试图在没有任何用户事件的情况下发送数据。因此我想到了 onPause() 因为 onPause() 总是被调用。但是 ViewPager 的功能不同。加载一个 fragment 时,也会加载相邻的 fragment 。我会成功地在第一个 fragment 和第三个 fragment 之间传递数据。但是第二个 fragment 的 onPause() 不会被调用,除非我导航到一些不相邻的 fragment (在我的例子中不存在)

Setter/Getters:我在一些帖子中看到有人说不要使用setter/getters(我还没有明白原因)Are getters and setters poor design? Contradictory advice seen

bundle :我还没有考虑过这个。由于我在这里再次感到困惑,我将如何使用 bundle 传递数据。(我应该在哪个方法中发送数据?以及如何发送数据?)

抱歉,如果我的问题听起来很愚蠢。我正在尝试理解 fragment ,我想知道在 viewpager 中的 fragment 之间传递数据的最佳方式。 提前谢谢你。

TabPAgerAdapter -->

  package com.jbandroid.model;

import com.jbandroid.fragment.LocationInfoFragment;
import com.jbandroid.fragment.PersonalInfoFragment;
import com.jbandroid.fragment.PostInfoFragment;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

public class TabsPagerAdapter extends FragmentPagerAdapter {

    public TabsPagerAdapter(FragmentManager fm){
        super(fm);
    }


    @Override
    public Fragment getItem(int index) {

        switch(index) {

        case 0 : //PostInfoFragment
                         return new PostInfoFragment();

        case 1 : //LocationInfoFragment
                        return new LocationInfoFragment();

        case 2 : //PersonalInfoFragment
                         return new PersonalInfoFragment();

        }

        return null;
    }

    @Override
    public int getCount() {
        // get item count - equal to number of tabs
        return 3;
    }

}

ViewPagerActivity -->

 package com.jbandroid;

public class SubmitPostActivity extends FragmentActivity implements ActionBar.TabListener,PostInfoFragment.setPostInfo,LocationInfoFragment.setLocationInfo{

    private ViewPager viewpager;
    private ActionBar actionBar;
    private TabsPagerAdapter mAdapter;
     FragmentManager manager;
     PersonalInfoFragment frag;
     List<String> location;
    /*private MenuItem myActionMenuItem;
      private Button myActionButton;*/


    //Tab titles
    private String[] tabs  = {"Post Info" , "Location Info" , "Personal Info" };



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

        viewpager = (ViewPager) findViewById(R.id.pager);
        actionBar = getActionBar();
        manager = getSupportFragmentManager();
        mAdapter = new TabsPagerAdapter(getSupportFragmentManager());
        //viewpager.setOffscreenPageLimit(2);
        viewpager.setAdapter(mAdapter);

        //actionBar.setHomeButtonEnabled(false);
        actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

        for (String tab : tabs){
            actionBar.addTab(actionBar.newTab().setText(tab).setTabListener(this));
        }

        if(savedInstanceState != null){
            actionBar.setSelectedNavigationItem( savedInstanceState.getInt("tab",0));
        }

        /**
         * on swiping the viewpager make respective tab selected
         * */

        viewpager.setOnPageChangeListener(new OnPageChangeListener() {

            @Override
            public void onPageSelected(int position) {
                // on changing the page
                // make respected tab selected
                actionBar.setSelectedNavigationItem(position);
            }

            @Override
            public void onPageScrolled(int arg0, float arg1, int arg2) {

            }

            @Override
            public void onPageScrollStateChanged(int arg0) {

            }
        });
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
    }



    @Override
    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }

    @Override
    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        // on tab selected
        // show respected fragment view

        viewpager.setCurrentItem(tab.getPosition());

    }

    @Override
    public void onTabUnselected(Tab tab, FragmentTransaction ft) {

    }



    @Override
    public void pass_location_details(List<String> location) {

         frag = (PersonalInfoFragment) manager.findFragmentByTag("android:switcher:" + viewpager.getId() + ":" + 2);
        frag.get_post_location_details(location);
        Log.d("submitarea", location.get(0));
    }


    @Override
    public void pass_post_details(List<String> post_details,ArrayList<CustomGallery> selected) {
         frag = (PersonalInfoFragment) manager.findFragmentByTag("android:switcher:" + viewpager.getId() + ":" + 2);
            frag.get_post_details(post_details,selected);
            Log.d("submitpostinfo","hello"+ post_details.get(5));
    }
    }

第一个 fragment (这里我尝试使用 onPause() 中的接口(interface)传递数据-->

    package com.jbandroid.fragment;
public class PostInfoFragment extends Fragment {

    private MenuItem myActionMenuItem;
    private Button myActionButton;
    private ActionBar actionBar;
    private String post_title, post_desc,post_status;

    private EditText submit_post_title, submit_post_desc;

        private Resources res;

    setPostInfo info;
    List<String> post_details;


    //RelativeLayout rel_submit_post_start_date,rel_submit_post_end_date;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_post_info,
                container, false);

        /*if(!imageLoader.isInited()){*/
        initImageLoader();
        /*}*/

        //handler = new Handler();


        submit_post_title = (EditText) rootView
                .findViewById(R.id.submit_post_title);
        submit_post_desc = (EditText) rootView
                .findViewById(R.id.submit_post_description);

        actionBar = getActivity().getActionBar();
        setHasOptionsMenu(true);

        post_details = new ArrayList<String>();
        res = getResources();

        setListeners();

        Log.d("postinfo_oncreate view", "postinfo_oncreate view");

        return rootView;

    }



    //interface to pass data to activity and then to PersonalInfoFragment
    public interface setPostInfo {
        //public void pass_post_details(List<String> post_details);
        public void pass_post_details(List<String> post_details,ArrayList<CustomGallery> selected);
    }


    //making sure if the parent activity has implemented interface
    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            info = (setPostInfo) activity;
        } catch (ClassCastException e) {

            throw new ClassCastException(activity.toString()
                    + "must implemet setPostInfo");
        }

         Log.d("postinfo_onattach", "postinfo_onattach");
    }


    //passing form inputs to personalinfofragments
    @Override
    public void onPause() {
        super.onPause();
        // setFormInputs();

        passFormInputs();  ---> passing in onPause() This executes successfully

         Log.d("postinfo_onPAuse", "postinfo_onPause");

    }


    //method to pass data to personalinfofragment
    private void passFormInputs() {
        try {
            post_title = submit_post_title.getText().toString();
            post_desc = submit_post_desc.getText().toString();
            post_status = "1";

            if(post_title != null && post_title.length() > 0 

                    && post_desc != null && post_desc.length() > 0
                    && post_status != null && post_status.length() > 0
                    ){
            post_details.add(post_title);
            post_details.add(post_desc);
            post_details.add(post_status);

            info.pass_post_details(post_details,dataT); -->here I am passing values via             
            }else{                                                activity to 3rd fragment
                Log.d("post_info", "values are null");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    //setting next button on actionbar
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);

        // Inflate the menu items for use in the action bar

        inflater.inflate(R.menu.mymenu, menu);

        // Here we get the action view we defined
        myActionMenuItem = menu.findItem(R.id.my_action);
        View actionView = myActionMenuItem.getActionView();

        // We then get the button view that is part of the action view
        if (actionView != null) {
            myActionButton = (Button) actionView.findViewById(R.id.action_btn);
            myActionButton.setText(R.string.txt_next);
            if (myActionButton != null) {
                // We set a listener that will be called when the return/enter
                // key is pressed
                myActionButton.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {

                        actionBar.setSelectedNavigationItem(1);
                    }
                });
            }
        }

    }

}

第二个 fragment -->

   package com.jbandroid.fragment;



public class LocationInfoFragment extends Fragment implements OnClickListener {

    private MenuItem myActionMenuItem;
    private Button myActionButton;
    private ActionBar actionBar;

    Dialog dialog;
    private EditText submit_post_exact_location;
    private TextView selected_country, selected_city, 
            submit_post_exact_time;
    String country, city, exact_location, exact_time;
    setLocationInfo info;

    List<String> location;

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

        View rootView = inflater.inflate(R.layout.fragment_location_info,
                container, false);
        actionBar = getActivity().getActionBar();
        setHasOptionsMenu(true);


        submit_post_exact_location = (EditText) rootView
                .findViewById(R.id.submit_post_exact_location);
        submit_post_exact_time = (TextView) rootView
                .findViewById(R.id.submit_post_exact_time);

        selected_country = (TextView) rootView
                .findViewById(R.id.selected_country);
        selected_city = (TextView) rootView.findViewById(R.id.selected_city);



        location = new ArrayList<String>();
        setListeners();

        return rootView;

    }

    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        super.onCreateOptionsMenu(menu, inflater);

        // Inflate the menu items for use in the action bar

        inflater.inflate(R.menu.mymenu, menu);

        // Here we get the action view we defined
        myActionMenuItem = menu.findItem(R.id.my_action);
        View actionView = myActionMenuItem.getActionView();

        // We then get the button view that is part of the action view
        if (actionView != null) {
            myActionButton = (Button) actionView.findViewById(R.id.action_btn);
            myActionButton.setText(R.string.txt_next);
            if (myActionButton != null) {
                // We set a listener that will be called when the return/enter
                // key is pressed
                myActionButton.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View v) {


                        actionBar.setSelectedNavigationItem(2);

                    }
                });
            }
        }
    }


    public interface setLocationInfo {
        public void pass_location_details(List<String> location);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        // This makes sure that the container activity has implemented
        // the callback interface. If not, it throws an exception
        try {
            info = (setLocationInfo) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + "must implement setLocationInfo");
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        //setLocationDetails();
    }

    @Override
    public void onPause() {
        super.onPause();
         setLocationDetails();   ----> doesnt executes since onPause isnt called when I                                      navigate to 3rd fragment as it is an adjacent fragment of this fragment
        // Log.d("location : onPause", area);
    }

    private void setLocationDetails() {
        try {

            exact_location = submit_post_exact_location.getText().toString();
            exact_time = submit_post_exact_time.getText().toString();
country = selected_country.getText().toString();
city =  selected_city.getText().toString();

            if (country != null && country.length() > 0
                    && !country.equalsIgnoreCase("select") && city != null
                    && city.length() > 0 && !city.equalsIgnoreCase("select")

                    && exact_location != null && exact_location.length() > 0
                    && exact_time != null && exact_time.length() > 0) {

                location.add(country);
                location.add(city);

                location.add(exact_location);
                location.add(exact_time);
                info.pass_location_details(location);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


}

在我的第三个 fragment 中,我试图获得这个值

         public class PersonalInfoFragment extends Fragment {
    List<String> post_details;
    List<String> location;
    Button submit;
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_personal_info,
                    container, false);
    submit = (Button)rootView.findViewById(R.id.submitBtn);
    submit.setOnClickListener(new OnClickListener() {

                        @Override
                        public void onClick(View v) {

                            //performing operations with the values obtained
                            setPostItems();

                            insertintodb();


                        }
                    });

    return rootView;
    }

    public void get_post_details(List<String> post_details,
                ArrayList<CustomGallery> selected) {            -->receiving values from
            this.post_details = post_details;                         1st fragment
            this.selected = selected;
            Log.d("personalfrag(postinfo)", "hello" + post_details.get(5));
        }


//receiving values from 2nd fragment
        public void get_post_location_details(List<String> location) {
            this.location = location;
            Log.d("personalfrag(locationinfo)", "hello" + location.get(0));
        }


    }

最佳答案

好的,我在 ViewPager 的两个选项卡之间传递数据(不仅仅是字符串)时遇到了同样的问题。所以这就是我所做的。 我使用接口(interface)在不同组件之间进行通信。

数据以这种方式传递:

Tab 1 -> Activity -> VewPageAdapter -> Tab 2
  1. 在选项卡 1 中

创建一个接口(interface)。

OnCartsDataListener mOncarOnCartsDataListener;


public interface OnCartsDataListener {

    public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels);

}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    try {
        mOncarOnCartsDataListener = (OnCartsDataListener)activity;
    }catch (ClassCastException e){

    }

}
// now call mOncarOnCartsDataListener.onCartsDataReceived(data) when you have the data
  1. Activity 中

实现接口(interface)并覆盖方法

ViewPagerAdapter adapter;
adapter = new ViewPagerAdapter(getSupportFragmentManager(), Titles, Numboftabs);

@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
    Log.d(TAG, "data received to Activity... send to view pager");
    adapter.onCartsDataReceived(cartsViewModels);
}

3.在ViewPagerAdapter中

同时实现了接口(interface)并重写了方法

@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
    Log.d(TAG, "data received to view pager... sending to tab 2");

    if(tab2!=null){
        tab2.onCartsDataReceived(cartsViewModels);
    }else{
        Log.d(TAG, "tab2 is null");
    }
} 
  1. 最后是选项卡 2

也实现了接口(interface)并覆盖了方法

@Override
public void onCartsDataReceived(ArrayList<CartsViewModel> cartsViewModels) {
    Log.d(TAG, "Finally ! received data to tab 2");
    if(cartsViewModels!=null){
        for(CartsViewModel cart : cartsViewModels){
            Log.d(TAG,"got it :"+cart.getCartName());
        }
    }
}

关于Android:在 viewpager fragment 之间传递数据的最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26358043/

有关Android:在 viewpager fragment 之间传递数据的最佳方法的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  4. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  5. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  6. Ruby 方法() 方法 - 2

    我想了解Ruby方法methods()是如何工作的。我尝试使用“ruby方法”在Google上搜索,但这不是我需要的。我也看过ruby​​-doc.org,但我没有找到这种方法。你能详细解释一下它是如何工作的或者给我一个链接吗?更新我用methods()方法做了实验,得到了这样的结果:'labrat'代码classFirstdeffirst_instance_mymethodenddefself.first_class_mymethodendendclassSecond使用类#returnsavailablemethodslistforclassandancestorsputsSeco

  7. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  8. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  9. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  10. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

随机推荐