2016-08-11 19 views
0

我試圖創建加載兩個片段之一的活動。第一個片段(SendFragment)將有一個文本框和一個按鈕,並將文本發送到第二個片段。第二個片段(DisplayFragment)將顯示接收到的文本。 MainActivity將首先加載SendFragment的佈局,然後在發送文本時加載DisplayFragment的佈局。嘗試加載片段佈局時停止從onCreateView的無限循環

當應用程序啓動時,調用SendFragment的onCreateView()時發生無限循環。該循環在OnCreateView()和該行之間重複出現以擴展SendFragment佈局。

如何只加載一次佈局並停止無限循環?

DisplayFragment.Java

package com.example.helloworld; 

import android.content.Context; 
import android.net.Uri; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 


/** 
* A simple {@link Fragment} subclass. 
* Activities that contain this fragment must implement the 
* {@link DisplayFragment.OnFragmentInteractionListener} interface 
* to handle interaction events. 
* Use the {@link DisplayFragment#newInstance} factory method to 
* create an instance of this fragment. 
*/ 
public class DisplayFragment extends Fragment { 
    // TODO: Rename parameter arguments, choose names that match 
    // the fragment initialization parameters, e.g. ARG_ITEM_NUMBER 
    private static final String ARG_MESSAGE = "param1"; 

    // TODO: Rename and change types of parameters 
    private String message; 

    private OnFragmentInteractionListener mListener; 

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

    /** 
    * Use this factory method to create a new instance of 
    * this fragment using the provided parameters. 
    * 
    * @param param1 Parameter 1. 
    * @return A new instance of fragment DisplayFragment. 
    */ 
    // TODO: Rename and change types and number of parameters 
    public static DisplayFragment newInstance(String param1) { 
     DisplayFragment fragment = new DisplayFragment(); 
     Bundle args = new Bundle(); 
     args.putString(ARG_MESSAGE, param1); 
     fragment.setArguments(args); 
     return fragment; 
    } 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     if (getArguments() != null) { 
      message = getArguments().getString(ARG_MESSAGE); 
     } 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     return inflater.inflate(R.layout.fragment_display, container, false); 
    } 

    // TODO: Rename method, update argument and hook method into UI event 
    public void onButtonPressed(Uri uri) { 
     if (mListener != null) { 
      mListener.onFragmentInteraction(uri); 
     } 
    } 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (context instanceof OnFragmentInteractionListener) { 
      mListener = (OnFragmentInteractionListener) context; 
     } else { 
      throw new RuntimeException(context.toString() 
        + " must implement OnFragmentInteractionListener"); 
     } 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 

    /** 
    * This interface must be implemented by activities that contain this 
    * fragment to allow an interaction in this fragment to be communicated 
    * to the activity and potentially other fragments contained in that 
    * activity. 
    * <p/> 
    * See the Android Training lesson <a href= 
    * "http://developer.android.com/training/basics/fragments/communicating.html" 
    * >Communicating with Other Fragments</a> for more information. 
    */ 
    public interface OnFragmentInteractionListener { 
     // TODO: Update argument type and name 
     void onFragmentInteraction(Uri uri); 
    } 
} 

SendFragment.Java

package com.example.helloworld; 

import android.content.Context; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.EditText; 


/** 
* A simple {@link Fragment} subclass. 
* Activities that contain this fragment must implement the 
* {@link SendFragment.OnMessageSentListener} interface 
* to handle interaction events. 
* Use the factory method to 
* create an instance of this fragment. 
*/ 
public class SendFragment extends Fragment { 

    private OnMessageSentListener mListener; 

    View view; 

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

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
          Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     if(view != null) { 
      ViewGroup parent = (ViewGroup) view.getParent(); 
      if (parent != null) 
       parent.removeView(view); 
     } 
     view = inflater.inflate(R.layout.fragment_send, container, false); 
     return view; 
    } 

    // TODO: Rename method, update argument and hook method into UI event 
    public void sendMessage(View v) { 

     if (mListener != null) { 
      EditText editText = (EditText) v.findViewById(R.id.edit_message); 
      String message = editText.getText().toString(); 
      mListener.onMessageSent(message); 
     } 
    } 

    @Override 
    public void onAttach(Context context) { 
     super.onAttach(context); 
     if (context instanceof OnMessageSentListener) { 
      mListener = (OnMessageSentListener) context; 
     } else { 
      throw new RuntimeException(context.toString() 
        + " must implement OnFragmentInteractionListener"); 
     } 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     mListener = null; 
    } 

    /** 
    * This interface must be implemented by activities that contain this 
    * fragment to allow an interaction in this fragment to be communicated 
    * to the activity and potentially other fragments contained in that 
    * activity. 
    * <p> 
    * See the Android Training lesson <a href= 
    * "http://developer.android.com/training/basics/fragments/communicating.html" 
    * >Communicating with Other Fragments</a> for more information. 
    */ 
    public interface OnMessageSentListener { 
     // TODO: Update argument type and name 
     void onMessageSent(String s); 
    } 

} 

MainActivity.Java

package com.example.helloworld; 

import android.os.Bundle; 
import android.support.v4.app.FragmentActivity; 
import android.support.v4.app.FragmentTransaction; 

public class MainActivity extends FragmentActivity 
    implements com.example.helloworld.SendFragment.OnMessageSentListener { 

    public final static String EXTRA_MESSAGE = "com.example.myfirstapp.MESSAGE"; 

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

     // Check that the activity is using the layout version with 
     // the fragment_container FrameLayout 
     if (findViewById(R.id.fragment_container) != null) { 

      // However, if we're being restored from a previous state, 
      // then we don't need to do anything and should return or else 
      // we could end up with overlapping fragments. 
      if (savedInstanceState != null) { 
       return; 
      } 

      // Create a new Fragment to be placed in the activity layout 
      SendFragment firstFragment = new SendFragment(); 

      // In case this activity was started with special instructions from an 
      // Intent, pass the Intent's extras to the fragment as arguments 
      firstFragment.setArguments(getIntent().getExtras()); 

      // Add the fragment to the 'fragment_container' FrameLayout 
      getSupportFragmentManager().beginTransaction() 
        .add(R.id.fragment_container, firstFragment).commit(); 
     } 
    } 

    public void onMessageSent(String s) { 

     DisplayFragment display = (DisplayFragment) 
       getSupportFragmentManager().findFragmentById(R.id.display_fragment); 

     if (display != null) { 

      // do something?? 

     } 
     else { 

      DisplayFragment newFragment = DisplayFragment.newInstance(s); 

      FragmentTransaction transaction = getSupportFragmentManager().beginTransaction(); 

      // Replace whatever is in the fragment_container view with this fragment, 
      // and add the transaction to the back stack so the user can navigate back 
      transaction.replace(R.id.fragment_container, newFragment); 
      transaction.addToBackStack(null); 

      // Commit the transaction 
      transaction.commit(); 

     } 

    } 
} 

fragment_display.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.helloworld.DisplayFragment"> 

    <!-- TODO: Update blank fragment layout --> 
    <fragment android:name="com.example.helloworld.DisplayFragment" 
     android:id="@+id/display_fragment" 
     android:layout_weight="1" 
     android:layout_width="0dp" 
     android:layout_height="match_parent"> 
    <TextView 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:text="@string/hello_blank_fragment" /> 
    </fragment> 

</FrameLayout> 

fragment_send.xml

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context="com.example.helloworld.SendFragment"> 


    <fragment android:name="com.example.helloworld.SendFragment" 
     android:id="@+id/send_fragment" 
     android:layout_weight="1" 
     android:layout_width="0dp" 
     android:layout_height="match_parent"> 
    <LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:tools="http://schemas.android.com/tools" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent" 
     android:orientation="horizontal"> 

     <EditText android:id="@+id/edit_message" 
      android:layout_weight="1" 
      android:layout_width="0dp" 
      android:layout_height="wrap_content" 
      android:hint="@string/edit_message" /> 

     <Button 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:text="@string/button_send" 
      android:onClick="sendMessage" /> 

    </LinearLayout> 
    </fragment> 


</FrameLayout> 

activity_main.xml中

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/fragment_container" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" /> 

回答

2

更改onCreateView()到 -

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

     return inflater.inflate(R.layout.fragment_send, container, false); 
    } 

更新 -

要從你的片段刪除<fragment>組件'佈局。這不是必需的,因爲您已經動態地初始化您的片段。

+0

我試過這個改變,但沒有運氣。當調用inflater.inflate方法時,似乎仍然存在無限循環。 – MrWerbenjagermanjensen

+0

檢查更新後的答案。 –

+0

它的工作!由於片段組件具有ID,我還必須將ID添加回每個片段佈局的FrameLayout組件。 – MrWerbenjagermanjensen