วิธีป้องกันคนโง่ในการจัดการ Fragment ในการเปลี่ยนทิศทาง


87
public class MainActivity extends Activity implements MainMenuFragment.OnMainMenuItemSelectedListener {

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

    FragmentManager fragmentManager = getFragmentManager();
    FragmentTransaction fragmentTransaction = fragmentManager
            .beginTransaction();

    // add menu fragment
    MainMenuFragment myFragment = new MainMenuFragment();
    fragmentTransaction.add(R.id.menu_fragment, myFragment);

    //add content
    DetailPart1 content1= new DetailPart1 ();
    fragmentTransaction.add(R.id.content_fragment, content1);
    fragmentTransaction.commit();

}
public void onMainMenuSelected(String tag) {
  //next menu is selected replace existing fragment
}

ฉันมีความต้องการที่จะแสดงมุมมองรายการสองรายการควบคู่กันเมนูทางซ้ายและเนื้อหาทางด้านขวา โดยค่าเริ่มต้นเมนูแรกจะถูกเลือกและเนื้อหาจะแสดงทางด้านขวา Fragment ที่แสดงเนื้อหามีดังต่อไปนี้:

public class DetailPart1 extends Fragment {
  ArrayList<HashMap<String, String>> myList = new ArrayList<HashMap<String, String>>();
  ListAdapter adap;
  ListView listview;

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

       if(savedInstanceState!=null){
        myList = (ArrayList)savedInstanceState.getSerializable("MYLIST_obj");
        adap = new LoadImageFromArrayListAdapter(getActivity(),myList );
        listview.setAdapter(adap);
       }else{
        //get list and load in list view
        getlistTask = new GetALLListTasks().execute();
    }


     @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.skyview_fragment, container,false);
           return v;
        }


     @Override
      public void onSaveInstanceState(Bundle outState) {
         super.onSaveInstanceState(outState);
          outState.putSerializable("MYLIST_obj", myList );
        }
    }

onActivityCreated และ onCreateView จะเรียกว่าเป็นครั้งที่สอง มีตัวอย่างมากมายที่ใช้ชิ้นส่วน เนื่องจากฉันเป็นผู้เริ่มต้นในเรื่องนี้ฉันจึงไม่สามารถเชื่อมโยงตัวอย่างกับปัญหาของฉันได้ ฉันต้องการวิธีพิสูจน์คนโง่เพื่อจัดการกับการเปลี่ยนแปลงการวางแนว ฉันไม่ได้ประกาศandroid:configChangesในไฟล์รายการ ฉันต้องการให้กิจกรรมทำลายและสร้างใหม่เพื่อที่ฉันจะได้ใช้เลย์เอาต์ที่แตกต่างกันในโหมดแนวนอน


โดยปกติแล้วการเปลี่ยนแปลงการวางแนวของชิ้นส่วนจะได้รับการดูแลโดยที่คุณไม่จำเป็นต้องทำอะไรเลย แล้วอะไรคือปัญหาที่คุณพบเมื่อเปลี่ยนการวางแนว?
Alexander Kulyakhtin

Alex ฉันต้องการแฟรกเมนต์คลาส DetailPart1 เพื่อแสดงเลย์เอาต์ด้วย listView ในโหมดแนวตั้งและเลย์เอาต์ด้วย Grid View ในโหมดแนวนอนสำหรับสิ่งนี้ฉันต้องสร้างแฟรกเมนต์ใหม่ทุกครั้ง แต่ฉันไม่ต้องการโหลดเร็กคอร์ดเดียวกันอีกดังนั้นฉัน เก็บไว้ที่ onSaveInstanceState แต่โค้ดด้านบนสร้าง DetailPart1 ซ้ำสองครั้งฉันต้องรู้รหัสที่หายไปซึ่งทำให้มันทำงานได้ตามต้องการ
user1811741

คำตอบ:


132

คุณกำลังสร้างส่วนใหม่ทุกครั้งที่คุณเปิดหน้าจอในกิจกรรมของคุณแต่คุณยังคงรักษาคนเก่าด้วยonCreate(); super.onCreate(savedInstanceState);ดังนั้นอาจตั้งค่าแท็กและค้นหาแฟรกเมนต์หากมีอยู่หรือส่งบันเดิล null ไปยัง super

ฉันต้องใช้เวลาสักพักในการเรียนรู้และมันอาจจะเป็น bi **** จริงๆเมื่อคุณทำงานกับสิ่งต่างๆเช่น viewpager

ฉันขอแนะนำให้คุณอ่านเกี่ยวกับเศษเสี้ยวเป็นเวลาพิเศษเนื่องจากครอบคลุมหัวข้อที่แน่นอนนี้

นี่คือตัวอย่างของวิธีจัดการชิ้นส่วนในการเปลี่ยนแปลงการวางแนวปกติ:

กิจกรรม :

public class MainActivity extends FragmentActivity {

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

        if (savedInstanceState == null) {
            TestFragment test = new TestFragment();
            test.setArguments(getIntent().getExtras());
            getSupportFragmentManager().beginTransaction().replace(android.R.id.content, test, "your_fragment_tag").commit();
        } else {
            TestFragment test = (TestFragment) getSupportFragmentManager().findFragmentByTag("your_fragment_tag");
        }
    }
}

ส่วน :

public class TestFragment extends Fragment {

    public static final String KEY_ITEM = "unique_key";
    public static final String KEY_INDEX = "index_key";
    private String mTime;

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

        if (savedInstanceState != null) {
            // Restore last state
            mTime = savedInstanceState.getString("time_key");
        } else {
            mTime = "" + Calendar.getInstance().getTimeInMillis();
        }

        TextView title = (TextView) view.findViewById(R.id.fragment_test);
        title.setText(mTime);

        return view;
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("time_key", mTime);
    }
}

ขอบคุณ Warpzit สำหรับความพยายามของคุณ แต่ฉันจะดีใจถ้าคุณอธิบายในรหัสเกี่ยวกับประเด็นของคุณวิธีแก้ไขรหัสของฉันเพื่อจัดการกับการเปลี่ยนแปลงการวางแนวโดยไม่ต้องโหลดส่วนใหม่
user1811741

1
ดังนั้นฉันต้องเปลี่ยนเค้าโครงของส่วนที่จะเปลี่ยนในการวางแนว แต่ฉันไม่ต้องการโหลดระเบียนทั้งหมดซ้ำสิ่งที่ฉันทำคือ 1. เพิ่ม android: configchanges = "orientation" ในรายการ 2. แทนที่ onConfigurationChanged ในส่วนและตรวจจับการวางแนว และซ่อน / แสดง listview หรือ gridview ขึ้นอยู่กับการวางแนวนี่คือวิธีที่ถูกต้อง?
user1811741

@ user1811741 อัปเดตด้วยตัวอย่าง ฉันหวังว่ามันจะชี้แจงทุกอย่าง
Warpzit

@Warpzit จะจัดการสถานการณ์เดียวกันได้อย่างไรในกรณีของการใช้งาน ViewPager Fragment เนื่องจาก ViewPager ดูแลส่วนที่แสดงทั้งหมด .. คำแนะนำใด ๆ
CoDe

1
@Shubh ฉันเชื่อว่า viewpager จัดการสิ่งนี้ได้อย่างถูกต้องหากไม่เป็นเช่นนั้นคุณจะต้องแทนที่การใช้งาน getItem เพื่อให้เหมาะกับความต้องการของคุณ หวังว่าจะชี้คุณไปในทิศทางที่ถูกต้องหากไม่ตั้งคำถามที่เหมาะสม :)
Warpzit

21

แนวทางที่ดีเกี่ยวกับวิธีการเก็บข้อมูลระหว่างการเปลี่ยนแปลงการปฐมนิเทศและการพักผ่อนหย่อนใจกิจกรรมที่สามารถพบได้ในแนวทางหุ่นยนต์

สรุป:

  1. ทำให้ชิ้นส่วนของคุณสามารถเก็บรักษาได้:

    setRetainInstance(true);
    
  2. สร้างส่วนใหม่เฉพาะในกรณีที่จำเป็น (หรืออย่างน้อยก็ใช้ข้อมูลจากมัน)

    dataFragment = (DataFragment) fm.findFragmentByTag("data");
    
    // create the fragment and data the first time
    if (dataFragment == null) {
    

1
ดีประหยัดเวลาของฉันวา
Arjun saini
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.