SORU
31 EKİM 2011, PAZARTESİ


ViewPager ve parçaları — 'parçasını saklamak için doğru yol ne s'in devlet?

Parçaları bazı modüllere UI mantık ayrımı için çok güzel gibi duruyor. Ama ViewPager birlikte ömrü benim için hala puslu. Guru düşünceler çok gerekli!

Edit

Aptal çözüm aşağıda ;-)

Kapsam

Ana faaliyet parçaları ile ViewPager vardır. Bu parçalar biraz (submain) faaliyetleri, parçaları diğer mantık' veri aktivite içinde geri arama arayüzü ile doldurulur. farklı uygulamak Ve her şey ilk fırlatma ama! gayet iyi çalışıyor...

Sorun

Etkinlik yapmak ViewPager'In parçaları. bu yüzden yeniden (yönünü değiştirmek vb.) alır Kod (da bulacaksınız aşağıda) diyor her zaman faaliyettir oluşturulan çalışıyorum oluşturmak için yeni ViewPager adaptör parçaları ile aynı parçaları (belki de sorun bu.) ama FragmentManager zaten tüm bu parçalar saklı bir yerde (nerede?) ve başlar bu eğlence mekanizması. Eğlence mekanizması "eski" parçanın onAttach, onCreateView, vb. aramalar çok benim geri arama arayüzü Etkinlik uygulanan yöntem ile veri başlatmak için arayın. Ama bu yöntem Aktivitenin onCreate yöntemi ile oluşturulan yeni oluşturulan bir parçasına işaret eder.

Sorun

Belki yanlış ama desen bile 3 Pro Android kitap hakkında pek bir şey yok kullanıyorum. Yanilütfenbana bir-iki yumruk vermek ve bunu doğru şekilde yapmak için nasıl. Çok teşekkürler!

Kod

Ana Faaliyet

public class DashboardActivity extends BasePagerActivity implements OnMessageListActionListener {

private MessagesFragment mMessagesFragment;

@Override
protected void onCreate(Bundle savedInstanceState) {
    Logger.d("Dash onCreate");
    super.onCreate(savedInstanceState);

    setContentView(R.layout.viewpager_container);
    new DefaultToolbar(this);

    // create fragments to use
    mMessagesFragment = new MessagesFragment();
    mStreamsFragment = new StreamsFragment();

    // set titles and fragments for view pager
    Map<String, Fragment> screens = new LinkedHashMap<String, Fragment>();
    screens.put(getApplicationContext().getString(R.string.dashboard_title_dumb), new DumbFragment());
    screens.put(getApplicationContext().getString(R.string.dashboard_title_messages), mMessagesFragment);

    // instantiate view pager via adapter
    mPager = (ViewPager) findViewById(R.id.viewpager_pager);
    mPagerAdapter = new BasePagerAdapter(screens, getSupportFragmentManager());
    mPager.setAdapter(mPagerAdapter);

    // set title indicator
    TitlePageIndicator indicator = (TitlePageIndicator) findViewById(R.id.viewpager_titles);
    indicator.setViewPager(mPager, 1);

}

/* set of fragments callback interface implementations */

@Override
public void onMessageInitialisation() {

    Logger.d("Dash onMessageInitialisation");
    if (mMessagesFragment != null)
        mMessagesFragment.loadLastMessages();
}

@Override
public void onMessageSelected(Message selectedMessage) {

    Intent intent = new Intent(this, StreamActivity.class);
    intent.putExtra(Message.class.getName(), selectedMessage);
    startActivity(intent);
}

BasePagerActivity Yardımcısı aka

public class BasePagerActivity extends FragmentActivity {

BasePagerAdapter mPagerAdapter;
ViewPager mPager;
}

Bağdaştırıcı

public class BasePagerAdapter extends FragmentPagerAdapter implements TitleProvider {

private Map<String, Fragment> mScreens;

public BasePagerAdapter(Map<String, Fragment> screenMap, FragmentManager fm) {

    super(fm);
    this.mScreens = screenMap;
}

@Override
public Fragment getItem(int position) {

    return mScreens.values().toArray(new Fragment[mScreens.size()])[position];
}

@Override
public int getCount() {

    return mScreens.size();
}

@Override
public String getTitle(int position) {

    return mScreens.keySet().toArray(new String[mScreens.size()])[position];
}

// hack. we don't want to destroy our fragments and re-initiate them after
@Override
public void destroyItem(View container, int position, Object object) {

    // TODO Auto-generated method stub
}

}

Parça

public class MessagesFragment extends ListFragment {

private boolean mIsLastMessages;

private List<Message> mMessagesList;
private MessageArrayAdapter mAdapter;

private LoadMessagesTask mLoadMessagesTask;
private OnMessageListActionListener mListener;

// define callback interface
public interface OnMessageListActionListener {
    public void onMessageInitialisation();
    public void onMessageSelected(Message selectedMessage);
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
    // setting callback
    mListener = (OnMessageListActionListener) activity;
    mIsLastMessages = activity instanceof DashboardActivity;

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    inflater.inflate(R.layout.fragment_listview, container);
    mProgressView = inflater.inflate(R.layout.listrow_progress, null);
    mEmptyView = inflater.inflate(R.layout.fragment_nodata, null);
    return super.onCreateView(inflater, container, savedInstanceState);
}

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

    // instantiate loading task
    mLoadMessagesTask = new LoadMessagesTask();

    // instantiate list of messages
    mMessagesList = new ArrayList<Message>();
    mAdapter = new MessageArrayAdapter(getActivity(), mMessagesList);
    setListAdapter(mAdapter);
}

@Override
public void onResume() {
    mListener.onMessageInitialisation();
    super.onResume();
}

public void onListItemClick(ListView l, View v, int position, long id) {
    Message selectedMessage = (Message) getListAdapter().getItem(position);
    mListener.onMessageSelected(selectedMessage);
    super.onListItemClick(l, v, position, id);
}

/* public methods to load messages from host acitivity, etc... */
}

Çözüm

Aptal çözüm putFragment ile onSaveİnstanceState (ana Faaliyet) içindeki parçaları kaydetmek ve getFragment üzerinden onCreate içinde onları almak için. Ama yine de bazı şeyler... kod aşağıda: gibi değil garip bir his var

    @Override
protected void onSaveInstanceState(Bundle outState) {

    super.onSaveInstanceState(outState);
    getSupportFragmentManager()
            .putFragment(outState, MessagesFragment.class.getName(), mMessagesFragment);
}

protected void onCreate(Bundle savedInstanceState) {
    Logger.d("Dash onCreate");
    super.onCreate(savedInstanceState);

    ...
    // create fragments to use
    if (savedInstanceState != null) {
        mMessagesFragment = (MessagesFragment) getSupportFragmentManager().getFragment(
                savedInstanceState, MessagesFragment.class.getName());
                StreamsFragment.class.getName());
    }
    if (mMessagesFragment == null)
        mMessagesFragment = new MessagesFragment();
    ...
}

CEVAP
10 Mart 2012, CUMARTESİ


FragmentPagerAdapter FragmentManager için bir parça ekler, parça yer alacak özel bir etiket belirli bir pozisyona bağlı olarak kullanır. FragmentPagerAdapter.getItem(int position) bu pozisyon için bir parça yok sadece denir. Dönen sonra, Android zaten/kaydedilen bu özel konumu için bir parçasını oluşturan ve sadece onunla yeniden kurmaya çalışır yani FragmentManager.findFragmentByTag(), yerine yeni bir tane oluşturmak ile göreceksiniz. Tüm bu FragmentPagerAdapter kullanırken ücretsiz olarak geliyor ve her zamanki getItem(int) yöntemin bölümü hazırlama kuralların varmış olmasıdır.

Eğer FragmentPagerAdapter, Activity.onCreate(Bundle) yeni bir parça her zaman oluşturmak için iyi bir fikir değildir bir kullanmıyor olsak bile. Fark ettiğiniz gibi, bir parça FragmentManager eklendiğinde, dönen sonra sizin için oluşturulur ve tekrar eklemeye gerek yok. Bunu yaparken olduğu parçaları ile çalışırken hatalara yol açabilir.

Parçaları ile çalışırken normal bir yaklaşımdır bu

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    ...

    CustomFragment fragment;
    if (savedInstanceState != null) {
        fragment = (CustomFragment) getSupportFragmentManager().findFragmentByTag("customtag");
    } else {
        fragment = new CustomFragment();
        getSupportFragmentManager().beginTransaction().add(R.id.container, fragment, "customtag").commit(); 
    }

    ...

}

Adaptör için ** 23, feragat parça yönetimi kullanırken, ve yukarıdaki adımları gerçekleştirmek gerekmez. Varsayılan olarak, yalnızca geçerli konum FragmentStatePagerAdapter kullandığınız sürece, onları yok etmese de arkasında önünde ve bir Parça ön yük olacaktır. Bu ViewPager.setOffscreenPageLimit(int) tarafından kontrol edilir. Bu nedenle, doğrudan adaptör dışında parçaları yöntemleri çağırmak hayatta bile olmayabilir çünkü geçerli olması için garanti edilmez.

Kesmek uzun lafın kısası, çözüm için kullanın putFragment edebilmek için bir başvuru daha sonra değil, o yüzden deli, ve bu yüzden aksine normal şekilde kullanın parçaları zaten (yukarıda). Parça adaptör ile, sizin kişisel eklenmez çünkü zor bir referans aksi takdirde elde etmek mümkündür. Ona güveniyor beri sadece offscreenPageLimit Her zaman istediğiniz parçaları yüklemek için yeterince yüksek olduğundan emin olun, mevcut olmak. Bu ViewPager tembel yükleme yetenekleri atlar, ama uygulama için ne arzu gibi görünüyor.

Başka bir yaklaşım FragmentPageAdapter.instantiateItem(View, int) geçersiz kılar ve parça iade etmeden önce süper çağrısından bir başvuru (zaten varsa bu parçayı bulmak için mantığı vardır) kurtarmaktır.

Daha dolgun bir görüntü için, FragmentPagerAdapter (kısa) ve ViewPager (uzun) kaynak bazılarına bir göz var.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • bashirsultani

    bashirsultan

    22 Mart 2010
  • Christopher Bill

    Christopher

    30 NİSAN 2009
  • xiaoyu85

    xiaoyu85

    20 ŞUBAT 2010