2012-04-01 18 views
6

Tôi có một chính TabActivity có hai tab, A và B (hiện tại). Tab A tải một FragmentActivity (mã được đưa ra dưới đây) mà chỉ mang một FrameLayout, vì vậy tôi có thể tải Fragments của tôi cho Tab cụ thể trong đó.FragmentManager.popBackStack() không chỉ đơn giản tải Fragment trước

Phân đoạn đầu tiên có một số TextView và ListView. Dữ liệu được lấy từ một dịch vụ web. Khi tôi nhấp vào một mục của ListView, tôi tải chi tiết của mục đó trong một Fragment khác (điều này cũng xuất phát từ một dịch vụ web) và thay thế Fragment hiện tại (với ListView và các điều khiển khác) bằng một đoạn chi tiết khác.

Để đạt được điều này, tôi đang sử dụng thư viện số android-support-v4.jar để sử dụng Phân đoạn như chúng được ưu tiên. XML

Tab của một FragmentActivity của:

<?xml version="1.0" encoding="utf-8"?> 
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical" > 

     <FrameLayout 
      android:id="@+id/updates_frame" 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      android:background="@drawable/background"/> 
    </LinearLayout> 

Tab của một FragmentActivity Java mã:

public class UpdatesFragmentActivity extends FragmentActivity implements 
    IUpdateNotifier { 

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

     //Load Initial Fragment into FrameLayout 
     //I am adding this Fragment to BackStack 
     Fragment newFragment = new UpdatesFragment(); 
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.addToBackStack(null); 
     ft.add(R.id.updates_frame, newFragment); 
     ft.commit(); 
    } 

    //This is an Interface method which I call with the clicked "FEED" object to load its detail in another Fragment 
    @Override 
    public void onFeedSelected(Feed feed) { 
     // Instantiate a new fragment. 
     Fragment newFragment = new FeedDetailFragment(feed); 

     // Add the fragment to the activity, pushing this transaction 
     // on to the back stack. 
     FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); 
     ft.replace(R.id.updates_frame, newFragment); 
     ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN); 
     ft.addToBackStack(null); 
     ft.commit(); 
    } 

    //This is another Interface Method which I call when the user presses "BACK". 
    //I am trying to load the previously loaded Fragment, which I added to BackStack. 
    //But this causes reconstruction of the previously loaded fragment. LIST in this case 
    //which call the web service. I DONT WANT TO CALL SERVICE AGAIN. 
    @Override 
    public void onBackPressed() { 
     FragmentManager fm = getSupportFragmentManager(); 
     if (fm.getBackStackEntryCount() > 0) { 
      fm.popBackStack(); 
     } 
    } 
} 

Tôi đã tạo ra một giao diện IUpdateNotifier, trong đó có hai phương pháp:

public void onFeedSelected(Feed feed); 
public void onBackPressed(); 

Phụ huynh UpdatesFragmentActivity thực hiện các phương pháp này. Tôi gọi những phương pháp này từ trẻ em Các mảnh vỡ sau khi hành động.

  1. tôi gọi onFeedSelected (thức ăn Feed) từ Fragment trong đó có một ListView. Tôi gửi mục nguồn cấp dữ liệu được nhấp vào cho phụ huynh FragmentActivity, vì vậy nó tải một Fragment khác có chứa chi tiết nguồn cấp dữ liệu đó.
  2. Tôi gọi onBackPressed() từ chi tiết nguồn cấp dữ liệu thứ hai Phân đoạn khi người dùng nhấn một nút được cho là sẽ mang lại phân đoạn đầu tiên chứa ListView với các điều khiển khác. Như bạn thấy, tôi cố gắng gọi popBackStack FragmentManager của() phương pháp để mang lại rằng Fragment đầu tiên ...

Nhưng Fragment đầu tiên được làm mới và tải tất cả các dữ liệu từ dịch vụ web.

Thực ra tôi không thể nhận và lưu trữ dữ liệu chỉ một lần hoặc cũng không cập nhật thường xuyên trong một khoảng thời gian nào đó. Người dùng có thể cập nhật danh sách khi muốn. Ban đầu, danh sách tải 10 mục hàng đầu từ dịch vụ và sau đó người dùng có thể nhấp vào nút "Thêm" ở cuối danh sách nếu anh ta muốn tải thêm các mục.

Nó sẽ tải 10 mục tiếp theo, v.v. Nhưng tôi nghĩ rằng tôi có thể lưu trữ ArrayList được truy xuất trong một số biến trong UpdatesFragmentActivity và sau đó chỉ gán lại ArrayList vào bộ điều hợp danh sách thay vì tải dữ liệu từ dịch vụ, nhưng tôi không biết cách làm cho Fragment không gọi lại dịch vụ.

Tôi muốn ứng dụng hoạt động như khi tôi nhấp vào tab 2 và sau đó nhấp lại vào tab 1. Nó chỉ đơn giản cho thấy dữ liệu được tải như thể bị ẩn và không gọi dịch vụ.

Tôi làm cách nào để đạt được điều này?

+0

bạn có nhận được giải pháp nào không –

Trả lời

4

Mẫu thiết kế của bạn bị thiếu sót do sự phân tách mối quan tâm kém. Việc cập nhật dữ liệu nên được tách riêng khỏi giao diện người dùng, do đó khi người dùng quay lại Phân đoạn trước, nó sẽ không có gì liên quan đến việc tải dữ liệu từ dịch vụ web.

Có một vài cách khắc phục dễ dàng nhưng tôi không biết điều gì sẽ hoạt động tốt nhất khi bạn đã đưa ra ít bối cảnh cho vấn đề.

Tùy chọn đầu tiên là giới thiệu màn hình Splash khi khởi động. Hoạt động này sẽ sử dụng số AsyncTask để tải xuống dữ liệu bạn cần từ dịch vụ web. Điều này hoạt động tốt nếu bạn chỉ muốn dữ liệu được tải xuống một lần trong suốt thời gian chạy của ứng dụng. Bạn sẽ đảm bảo không thêm Hoạt động này vào lịch sử để khi quay lại được nhấn từ hoạt động tiếp theo, sau đó ứng dụng sẽ thoát.

Một tùy chọn khác mà tôi đã sử dụng trong nhiều ứng dụng và tùy chọn tôi thích, là việc sử dụng Báo thức qua AlarmManager. Bạn có thể thiết lập một bản cập nhật định kỳ tại các khoảng thời gian cụ thể, AlarmManager thậm chí giúp bạn đến thời điểm nó chứa các bảng liệt kê thời gian. Báo thức sẽ kích hoạt broadcast receiver sẽ thực thi mã tùy chỉnh của bạn, sẽ tải xuống dữ liệu bạn cần từ dịch vụ web và lưu trữ nó.

Có hướng dẫn về cách tiếp cận này, có thể tìm thấy tại đây http://android.arnodenhond.com/tutorials/alarm-notification.

Cuối cùng; bạn không cần phải bật ngăn xếp trở lại để giải quyết vấn đề này, mặc dù bạn có thể làm điều này vì các lý do hoàn toàn khác nhau nhưng khó có thể nói mà không có thêm thông tin.

+0

Tôi thực sự xin lỗi vì không cung cấp đủ thông tin về vấn đề tôi đang gặp phải. Tôi đã cập nhật câu hỏi của tôi ... u có thể có một cái nhìn vào nó bây giờ ... tôi đã cố gắng giải thích vấn đề của tôi. – Aamir

+0

Tôi không thay đổi câu trả lời của mình vì tôi không đồng ý rằng bạn đã chọn cách tiếp cận tốt nhất. Câu trả lời ở trên sẽ hướng bạn đi đúng hướng. –

+0

Trên thực tế tôi không thể nhận và lưu trữ dữ liệu chỉ một lần cũng không cập nhật thường xuyên trên một số thời gian inervals, người dùng có thể cập nhật danh sách khi anh muốn .. Ban đầu danh sách tải 10 mục hàng đầu từ dịch vụ, sau đó người dùng có thể nhấp vào "More" nút ở cuối danh sách nếu anh ấy muốn tải thêm mục. nó sẽ tải 10 mục tiếp theo .. v.v. Tough tôi đánh giá cao rằng u chỉ cho tôi để AlarmManager mà tôi migh sử dụng trong một số kịch bản mà yêu cầu cập nhật định kỳ nhưng tôi không nghĩ rằng tôi có thể sử dụng AlarmManager trong tình huống này .. Nhưng tôi nghĩ rằng tôi có thể lưu trữ ArrayList lấy trong một số biến trong FragmentActivity. – Aamir

2

Câu hỏi của bạn không rõ ràng đủ, đặt câu hỏi đơn giản hơn và chính xác ... Và như bạn nói ở trên

popBackStack không tải đoạn cuối cùng, nó thường được sử dụng để bật toàn bộ stack:

fragmentManager.popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE); 

trước khi tải một đoạn

beginTransaction() 
replace() Or add() 
commit() 

đó là tất cả tôi có thể suy nghĩ về câu hỏi đó với

01.

Chúc may mắn

+0

Giải pháp của tôi là phân đoạnManager.popBackStack (0, FragmentManager.POP_BACK_STACK_INCLUSIVE); – JWqvist