【问题标题】:How to pass data between fragments如何在片段之间传递数据
【发布时间】:2011-07-08 20:23:23
【问题描述】:

我试图在我的程序中的两个片段之间传递数据。它只是一个存储在列表中的简单字符串。该列表在片段 A 中公开,当用户单击列表项时,我需要它显示在片段 B 中。内容提供者似乎只支持 ID,所以这不起作用。有什么建议吗?

【问题讨论】:

标签: android android-fragments


【解决方案1】:

为什么不使用捆绑包。从您的第一个片段开始,设置方法如下:

Fragment fragment = new Fragment();
Bundle bundle = new Bundle();
bundle.putInt(key, value);
fragment.setArguments(bundle);

然后在您的第二个片段中,使用以下方法检索数据:

Bundle bundle = this.getArguments();
int myInt = bundle.getInt(key, defaultValue);

Bundle 为许多数据类型提供了 put 方法。请看http://developer.android.com/reference/android/os/Bundle.html

【讨论】:

    【解决方案2】:

    如果您使用 Roboguice,您可以使用 Roboguice 中的 EventManager 来传递数据,而无需使用 Activity 作为接口。这是相当干净的IMO。

    如果您不使用 Roboguice,您也可以使用 Otto 作为事件总线:http://square.github.com/otto/

    20150909 更新:您现在也可以使用 Green Robot Event Bus 甚至 RxJava。取决于您的用例。

    【讨论】:

    • 我全心全意地支持 Donn 在这里所说的话。使用总线并解开所有这些东西并停止手动编写侦听器和回调。奥托 FTW。
    • 如果不想使用 RoboGuice,可以使用 Otto by Square。我现在经常使用 Otto,它很棒。 github.com/square/otto
    • 如果您喜欢 Otto,您可能还会喜欢 EventBus,它还提供线程处理。 github.com/greenrobot/EventBus
    • 如果两个片段同时可见,我可以看到事件总线策略有效,但是如果片段 A(假设它是一个 ListFragment)占据整个屏幕并选择一个列表项启动片段 B,它也占据了整个屏幕。 AFAIK,事件总线模式在 onResume/onPause 中注册/取消注册每个片段,所以我不确定如何应用它。
    • @Matthew 如果是这种情况,您需要在活动之间捆绑传递它们,然后在运行时将数据注入它们。
    【解决方案3】:

    来自Fragmentdocumentation

    您通常希望一个 Fragment 与另一个 Fragment 进行通信,例如根据用户事件更改内容。所有 Fragment 到 Fragment 的通信都是通过关联的 Activity 完成的。两个 Fragment 永远不应该直接通信。

    所以我建议您查看文档中的basic fragment training docs。它们非常全面,包含示例和演练指南。

    【讨论】:

      【解决方案4】:

      假设您有控制 Frag A 和 Fragment B 的 Activity AB。 在 Fragment A 中,您需要一个 Activity AB 可以实现的接口。 在示例 android 代码中,它们具有:

      private Callbacks mCallbacks = sDummyCallbacks;

      /*包含此片段的所有活动都必须实现的回调接口。此机制允许将项目选择通知活动。 */

      public interface Callbacks {
      /*Callback for when an item has been selected. */    
            public void onItemSelected(String id);
      }
      
      /*A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity. */    
      private static Callbacks sDummyCallbacks = new Callbacks() {
          @Override
          public void onItemSelected(String id) {
          }
      };
      

      Callback 接口被放置在您的一个 Fragment 中(假设是 Fragment A)。我认为这个 Callbacks 接口的目的就像 Frag A 中的一个嵌套类,任何 Activity 都可以实现。因此,如果 Fragment A 是电视,则 CallBacks 是允许 Activity AB 使用 Fragment A 的 TV Remote(接口)。我可能对细节有误,因为我是菜鸟,但我确实让我的程序在所有屏幕尺寸上都能完美运行,这就是我使用的。

      所以在片段 A 中,我们有: (我取自 Android 的示例程序)

      @Override
      public void onListItemClick(ListView listView, View view, int position, long id) {
      super.onListItemClick(listView, view, position, id);
      // Notify the active callbacks interface (the activity, if the
      // fragment is attached to one) that an item has been selected.
      mCallbacks.onItemSelected(DummyContent.ITEMS.get(position).id);
      //mCallbacks.onItemSelected( PUT YOUR SHIT HERE. int, String, etc.);
      //mCallbacks.onItemSelected (Object);
      }
      

      在 Activity AB 中,我们重写了 onItemSelected 方法:

      public class AB extends FragmentActivity implements ItemListFragment.Callbacks {
      //...
      @Override
      //public void onItemSelected (CATCH YOUR SHIT HERE) {
      //public void onItemSelected (Object obj) {
          public void onItemSelected(String id) {
          //Pass Data to Fragment B. For example:
          Bundle arguments = new Bundle();
          arguments.putString(“FragmentB_package”, id);
          FragmentB fragment = new FragmentB();
          fragment.setArguments(arguments);
          getSupportFragmentManager().beginTransaction().replace(R.id.item_detail_container, fragment).commit();
          }
      

      所以在 Activity AB 中,你基本上把所有东西都扔到一个 Bundle 中并传递给 B。如果你不确定如何使用 Bundle,请查看该类。

      我基本上是按照 Android 提供的示例代码进行的。带有 DummyContent 内容的那个。当您制作一个新的 Android 应用程序包时,它的名称为 MasterDetailFlow。

      【讨论】:

        【解决方案5】:

        1- 第一种方式是定义一个接口

        public interface OnMessage{
            void sendMessage(int fragmentId, String message);
        }
        
        public interface OnReceive{
            void onReceive(String message);
        }
        

        2- 在你的活动中实现 OnMessage 接口

        public class MyActivity implements OnMessage {
           ...
           @Override
           public void sendMessage(int fragmentId, String message){
               Fragment fragment = getSupportFragmentManager().findFragmentById(fragmentId);
               ((OnReceive) fragment).sendMessage();
           }
        }
        

        3- 在您的片段中实现 OnReceive 接口

        public class MyFragment implements OnReceive{
            ...
            @Override
            public void onReceive(String message){
                myTextView.setText("Received message:" + message);
            }
        }
        

        这是处理片段之间消息传递的样板版本。

        在片段之间处理数据传递的另一种方法是使用事件总线。

        1- 注册/注销事件总线

        @Override
        public void onStart() {
            super.onStart();
            EventBus.getDefault().register(this);
        }
        
        @Override
        public void onStop() {
            EventBus.getDefault().unregister(this);
            super.onStop();
        }
        

        2- 定义一个事件类

        public class Message{
            public final String message;
        
            public Message(String message){
                this.message = message;
            }
        }
        

        3- 在应用程序的任何位置发布此事件

        EventBus.getDefault().post(new Message("hello world"));
        

        4- 订阅该事件以在您的片段中接收它

        @Subscribe(threadMode = ThreadMode.MAIN)
        public void onMessage(Message event){
            mytextview.setText(event.message);
        }
        

        更多details, use cases, and an example project关于事件总线模式。

        【讨论】:

        【解决方案6】:

        在我的情况下,我必须从 FragmentB->FragmentA 向后发送数据,因此 Intents 不是一个选项,因为片段已经被初始化尽管所有 上述答案 strong> 听起来不错,它需要大量的样板代码来实现,所以我采用了一种更简单的方法 使用LocalBroadcastManager,它正是上面说了但没有所有讨厌的样板代码。下面分享一个例子。

        在发送片段中(片段 B)

        public class FragmentB {
        
            private void sendMessage() {
              Intent intent = new Intent("custom-event-name");
              intent.putExtra("message", "your message");
              LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
            }
         }
        

        在消息中要接收的片段(FRAGMENT A)

          public class FragmentA {
            @Override
            public void onCreate(Bundle savedInstanceState) {
        
              ...
        
              // Register receiver
              LocalBroadcastManager.getInstance(this).registerReceiver(receiver,
                  new IntentFilter("custom-event-name"));
            }
        
        //    This will be called whenever an Intent with an action named "custom-event-name" is broadcasted.
            private BroadcastReceiver receiver = new BroadcastReceiver() {
              @Override
              public void onReceive(Context context, Intent intent) {
                String message = intent.getStringExtra("message");
              }
            };
        }
        

        希望对某人有所帮助

        【讨论】:

        • 所以我使用了这段代码,似乎 onReceive 被调用了两次,不知道为什么。
        • 永远不要在片段中注册接收者,因为它会因为某种原因被注册两次
        【解决方案7】:

        这取决于片段的结构。如果您可以将 Fragment Class B 上的某些方法设为静态,并且目标 TextView 对象也静态,则可以直接在 Fragment Class A 上调用该方法。这比侦听器更好,因为该方法是即时执行的,而我们不这样做'不需要额外的任务来在整个活动中执行监听。请参见下面的示例:

        Fragment_class_B.setmyText(String yourstring);
        

        在片段 B 上,您可以将方法定义为:

        public static void setmyText(final String string) {
        myTextView.setText(string);
        }
        

        只是不要忘记在 Fragment B 上将 myTextView 设置为静态,并在 Fragment A 上正确导入 Fragment B 类。

        最近刚刚在我的项目上完成了该程序,并且有效。希望对您有所帮助。

        【讨论】:

        • 这会起作用(好吧,直到片段被销毁并重新创建,想想设备旋转)但是你正在紧密耦合片段;依赖片段(我们称之为“X”)在其代码中对另一个片段(“Y”)具有硬连线依赖。通过父活动更简洁,因为您可以将其留给活动来决定从哪里获取数据。例如,在手机上,您的 Activity 可能使用片段 X 和 Y,但在平板电脑上,您可能决定使用 X 和 Z。最好让 Activity(它知道存在哪些片段)充当中间人并连接到 Y 或 Z合适。
        • 如何从这个方法调用Asyntask
        【解决方案8】:

        你可以阅读这个文档。这个概念在这里得到了很好的解释http://developer.android.com/training/basics/fragments/communicating.html

        【讨论】:

        • 如果您只引用另一个 URL,请在问题上使用 cmets 而不是发布答案
        • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
        • 这没有提供问题的答案。要批评或要求作者澄清,请在他们的帖子下方发表评论 - 您可以随时评论自己的帖子,一旦您有足够的reputation,您就可以comment on any post
        • @Mez 我同意你的话。下次会尝试做同样的事情。
        • @jewirth 我不知道你为什么对我有偏见,因为上面提供的所有答案都有指向其他页面的链接。我没有那么多回购,所以我可以评论其他帖子。否则我只会这样做。
        【解决方案9】:

        我正在做一个类似的项目,我想我的代码可能对上述情况有所帮助

        这是我在做什么的概述

        我的项目有两个片段,分别称为“FragmentA”和“FragmentB

        -FragmentA 包含一个列表视图,当你点击FragmentA中的一个项目时,它的INDEX使用Communicator接口传递给FragmentB

        • 设计模式完全基于 java 接口的概念,即 "接口引用变量可以引用子类对象"
        • MainActivity实现fragmentA提供的接口(否则不能让接口引用变量指向MainActivity)
        • 在下面的代码中,通信器对象通过使用 fragmentA 中的“setCommunicator(Communicatot c)”方法来引用 MainActivity 的对象.
        • 我正在使用 MainActivity 的引用从 FrgamentA 触发接口的 respond() 方法。

          接口通信器定义在fragmentA中,这是为了提供对通信器接口的最小访问权限。

        下面是我完整的工作代码

        FragmentA.java

        public class FragmentA extends Fragment implements OnItemClickListener {
        
        ListView list;
        Communicator communicater;
        
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            return inflater.inflate(R.layout.fragmenta, container,false);
        }
        
        public void setCommunicator(Communicator c){
            communicater=c;
        }
        
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onActivityCreated(savedInstanceState);
            communicater=(Communicator) getActivity();
            list = (ListView) getActivity().findViewById(R.id.lvModularListView);
            ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
                    R.array.items, android.R.layout.simple_list_item_1);
            list.setAdapter(adapter);
            list.setOnItemClickListener(this);
        
        }
        
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
        communicater.respond(index);
        
        }
        
        public interface Communicator{
            public void respond(int index);
        }
        

        }

        fragmentB.java

        public class FragmentA extends Fragment implements OnItemClickListener {
        
        ListView list;
        Communicator communicater;
        
        
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            return inflater.inflate(R.layout.fragmenta, container,false);
        }
        
        public void setCommunicator(Communicator c){
            communicater=c;
        }
        
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            // TODO Auto-generated method stub
            super.onActivityCreated(savedInstanceState);
            communicater=(Communicator) getActivity();
            list = (ListView) getActivity().findViewById(R.id.lvModularListView);
            ArrayAdapter<?> adapter = ArrayAdapter.createFromResource(getActivity(),
                    R.array.items, android.R.layout.simple_list_item_1);
            list.setAdapter(adapter);
            list.setOnItemClickListener(this);
        
        }
        
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int index, long arg3) {
        communicater.respond(index);
        
        }
        
        public interface Communicator{
            public void respond(int index);
        }
        
        }
        

        MainActivity.java

        public class MainActivity extends Activity implements FragmentA.Communicator {
        FragmentManager manager=getFragmentManager();
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        
            FragmentA fragA=(FragmentA) manager.findFragmentById(R.id.fragmenta);
            fragA.setCommunicator(this);
        
        
        }
        
        @Override
        public void respond(int i) {
            // TODO Auto-generated method stub
        
        FragmentB FragB=(FragmentB) manager.findFragmentById(R.id.fragmentb);
        FragB.changetext(i);
        }
        
        
        
        }
        

        【讨论】:

        • 已发布的 FragmentB 代码与 FragmentA 相同。请纠正。谢谢。
        【解决方案10】:

        基本实现了Activity和fragment之间通信的接口。

        1) 主要活动

        public class MainActivity extends Activity implements SendFragment.StartCommunication
        {
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        }
        
        @Override
        public void setComm(String msg) {
        // TODO Auto-generated method stub
        DisplayFragment mDisplayFragment = (DisplayFragment)getFragmentManager().findFragmentById(R.id.fragment2);
        if(mDisplayFragment != null && mDisplayFragment.isInLayout())
        {
        mDisplayFragment.setText(msg);
        }
        else
        {
        Toast.makeText(this, "Error Sending Message", Toast.LENGTH_SHORT).show();
        }
        }
        }
        

        2) 发送者片段(fragment-to-Activity)

        public class SendFragment extends Fragment
        {
        StartCommunication mStartCommunicationListner;
        String msg = "hi";
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        View mView = (View) inflater.inflate(R.layout.send_fragment, container);
        final EditText mEditText = (EditText)mView.findViewById(R.id.editText1);
        Button mButton = (Button) mView.findViewById(R.id.button1);
        mButton.setOnClickListener(new OnClickListener() {
        
        @Override
        public void onClick(View arg0) {
        // TODO Auto-generated method stub
        msg = mEditText.getText().toString();
        sendMessage();
        }
        });
        return mView;
        }
        
        interface StartCommunication
        {
        public void setComm(String msg);
        }
        
        @Override
        public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        if(activity instanceof StartCommunication)
        {
        mStartCommunicationListner = (StartCommunication)activity;
        }
        else
        throw new ClassCastException();
        
        }
        
        public void sendMessage()
        {
        mStartCommunicationListner.setComm(msg);
        }
        
        }
        

        3) 接收者片段(Activity-to-fragment)

            public class DisplayFragment extends Fragment
        {
        View mView;
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        mView = (View) inflater.inflate(R.layout.display_frgmt_layout, container);
        return mView;
        }
        
        void setText(String msg)
        {
        TextView mTextView = (TextView) mView.findViewById(R.id.textView1);
        mTextView.setText(msg);
        }
        
        }
        

        我将此链接用于相同的解决方案,我希望有人会发现它有用。 非常简单和基本的例子。

        http://infobloggall.com/2014/06/22/communication-between-activity-and-fragments/

        【讨论】:

        • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效
        【解决方案11】:

        片段类 A

        public class CountryListFragment extends ListFragment{
        
            /** List of countries to be displayed in the ListFragment */
        
            ListFragmentItemClickListener ifaceItemClickListener;   
        
            /** An interface for defining the callback method */
            public interface ListFragmentItemClickListener {
            /** This method will be invoked when an item in the ListFragment is clicked */
            void onListFragmentItemClick(int position);
        }   
        
        /** A callback function, executed when this fragment is attached to an activity */  
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
        
            try{
                /** This statement ensures that the hosting activity implements ListFragmentItemClickListener */
                ifaceItemClickListener = (ListFragmentItemClickListener) activity;          
            }catch(Exception e){
                Toast.makeText(activity.getBaseContext(), "Exception",Toast.LENGTH_SHORT).show();
            }
        }
        

        片段B类

        public class CountryDetailsFragment extends Fragment {
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        
            /** Inflating the layout country_details_fragment_layout to the view object v */
            View v = inflater.inflate(R.layout.country_details_fragment_layout, null);
        
            /** Getting the textview object of the layout to set the details */ 
            TextView tv = (TextView) v.findViewById(R.id.country_details);      
        
            /** Getting the bundle object passed from MainActivity ( in Landscape   mode )  or from 
             *  CountryDetailsActivity ( in Portrait Mode )  
             * */
            Bundle b = getArguments();
        
            /** Getting the clicked item's position and setting corresponding  details in the textview of the detailed fragment */
            tv.setText("Details of " + Country.name[b.getInt("position")]);     
        
            return v;
            }
        
        }
        

        片段之间传递数据的主要Activity类

        public class MainActivity extends Activity implements ListFragmentItemClickListener {
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
        }
        
        
        /** This method will be executed when the user clicks on an item in the listview */
        @Override
        public void onListFragmentItemClick(int position) {
        
            /** Getting the orientation ( Landscape or Portrait ) of the screen */
            int orientation = getResources().getConfiguration().orientation;
        
        
            /** Landscape Mode */
            if(orientation == Configuration.ORIENTATION_LANDSCAPE ){
                /** Getting the fragment manager for fragment related operations */
                FragmentManager fragmentManager = getFragmentManager();
        
                /** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
                FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
        
                /** Getting the existing detailed fragment object, if it already exists. 
                 *  The fragment object is retrieved by its tag name  *
                 */
        Fragment prevFrag = fragmentManager.findFragmentByTag("in.wptrafficanalyzer.country.details");
        
                /** Remove the existing detailed fragment object if it exists */
                if(prevFrag!=null)
            fragmentTransaction.remove(prevFrag);           
        
                /** Instantiating the fragment CountryDetailsFragment */
          CountryDetailsFragment fragment = new CountryDetailsFragment();
        
                /** Creating a bundle object to pass the data(the clicked item's   position) from the activity to the fragment */ 
                Bundle b = new Bundle();
        
                /** Setting the data to the bundle object */
                b.putInt("position", position);
        
                /** Setting the bundle object to the fragment */
                fragment.setArguments(b);           
        
                /** Adding the fragment to the fragment transaction */
                fragmentTransaction.add(R.id.detail_fragment_container,   fragment,"in.wptrafficanalyzer.country.details");
        
                /** Adding this transaction to backstack */
                fragmentTransaction.addToBackStack(null);
        
                /** Making this transaction in effect */
                fragmentTransaction.commit();
        
            }else{          /** Portrait Mode or Square mode */
                /** Creating an intent object to start the CountryDetailsActivity */
                Intent intent = new Intent("in.wptrafficanalyzer.CountryDetailsActivity");
        
                /** Setting data ( the clicked item's position ) to this intent */
                intent.putExtra("position", position);
        
                /** Starting the activity by passing the implicit intent */
                startActivity(intent);          
              }
            }
         }
        

        详细活动类

        public class CountryDetailsActivity extends Activity{
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
        
            /** Setting the layout for this activity */
            setContentView(R.layout.country_details_activity_layout);
        
            /** Getting the fragment manager for fragment related operations */
            FragmentManager fragmentManager = getFragmentManager();
        
            /** Getting the fragmenttransaction object, which can be used to add, remove or replace a fragment */
            FragmentTransaction fragmentTransacton = fragmentManager.beginTransaction();
        
            /** Instantiating the fragment CountryDetailsFragment */
            CountryDetailsFragment detailsFragment = new CountryDetailsFragment();
        
            /** Creating a bundle object to pass the data(the clicked item's position) from the activity to the fragment */
            Bundle b = new Bundle();
        
            /** Setting the data to the bundle object from the Intent*/
            b.putInt("position", getIntent().getIntExtra("position", 0));
        
            /** Setting the bundle object to the fragment */
            detailsFragment.setArguments(b);
        
            /** Adding the fragment to the fragment transaction */
            fragmentTransacton.add(R.id.country_details_fragment_container, detailsFragment);       
        
            /** Making this transaction in effect */
            fragmentTransacton.commit();
        
            }
        }
        

        国家数组

        public class Country {
        
        /** Array of countries used to display in CountryListFragment */
        static String name[] = new String[] {
                "India",
                "Pakistan",
                "Sri Lanka",
                "China",
                "Bangladesh",
                "Nepal",
                "Afghanistan",
                "North Korea",
                "South Korea",
                "Japan",
                "Bhutan"
        };
        }
        

        欲了解更多详情,请访问此链接 [http://wptrafficanalyzer.in/blog/itemclick-handler-for-listfragment-in-android/]。有完整的例子..

        【讨论】:

          【解决方案12】:

          getParentFragmentManager().setFragmentResultListener 是 2020 年的做法。您唯一的限制是使用捆绑包来传递数据。查看docs 了解更多信息和示例。

          其他一些方法

          • 调用getActivity() 并将其转换为片段之间的共享活动,然后将其用作传递数据的桥梁。强烈不推荐使用此解决方案,因为它需要在 Activity 和 Fragments 之间进行cupelling,但在 KitKat 时代,它曾经是执行此操作的流行方式...
          • 使用回调。任何事件机制都可以。这将是一个 Java vanilla 解决方案。 FragmentManager 的好处是它不仅限于捆绑包。然而,不利的一面是,当片段管理器处于保存状态或活动被破坏时,您可能会遇到一些极端情况错误,其中您会弄乱活动生命周期并获得IllegalStateException 之类的异常。此外,它不支持跨处理通信。

          【讨论】:

            【解决方案13】:

            基本上,我们在这里处理 Fragment 之间的通信。片段之间的通信永远不可能直接进行。它涉及创建两个片段的上下文中的活动。

            您需要在发送片段中创建一个接口并在活动中实现该接口,该接口将缓和消息并传输到接收片段。

            【讨论】:

              猜你喜欢
              • 2015-08-21
              • 2016-11-21
              • 1970-01-01
              • 1970-01-01
              • 2018-09-25
              • 2020-12-08
              • 1970-01-01
              相关资源
              最近更新 更多