5

में फ्रैगमेंट के साथ नहीं बुलाया गया है, मैं Fragment एस को दिखाने के लिए एसीएल से ViewPager का उपयोग कर रहा हूं। सबसे पहले, ये टुकड़े जहां सभी ListFragment एस एक सूची है। मैं एक 2 कॉलम टेबल की नकल करने की कोशिश कर रहा हूं, इसलिए सूची में प्रत्येक तत्व में दो ऑब्जेक्ट्स की एक और सूची है। मैं चाहता हूं कि प्रत्येक सेल लंबे समय तक क्लिक करने योग्य हो (संपूर्ण सूची आइटम नहीं), इसलिए मैंने अपना खुद का कॉलमलाउट लागू किया (शायद इसे सेललाउट कहा जाना चाहिए)। प्रत्येक सूची आइटम में दो कॉलमलेआउट होते हैं जो लंबे समय से क्लिक करने योग्य होते हैं और getContextMenuInfo() लागू करते हैं ताकि यह जानकारी लौटा दी जा सके कि किस इकाई को लंबे समय से क्लिक किया गया था। यह विधि व्यूपेजर को देखती है, वर्तमान खंड के लिए पूछती है और फिर उस खंड से इकाई आईडी को वापस करने के लिए खंड को कॉल करता है जिसे लंबे समय से क्लिक किया गया था। सही पंक्ति प्राप्त करने के लिए खंड को करने की आवश्यकता है:onCreateView को ViewPager

getListView().getPositionForView(v) 

और यहां समस्या कहां शुरू होती है। कभी-कभी getListView()IllegalStateException फेंकता है "सामग्री दृश्य अभी तक नहीं बनाया गया"। अर्थात। onCreateView(...) नहीं कहा गया है। यह तब होता है जब कभी-कभी ऐप फिर से शुरू होता है। आज मैं अपने गैलेक्सी नेक्सस पर सेटिंग्स> डेवलपर विकल्पों में "गतिविधियों को न रखें" विकल्प सक्षम करके समस्या का पुन: उत्पादन करने में कामयाब रहा। मैं ऐप शुरू करता हूं, होम दबाता हूं और फिर ऐप को हालिया ऐप्स मेनू से फिर से खोलता हूं और अब, अगर मैं अपनी सूची में से किसी भी सेल्स पर लंबे समय से क्लिक करता हूं तो यह अपवाद फेंक दिया जाता है। कुछ डीबग आउटपुट से मैं यह सत्यापित करने में कामयाब रहा कि क्रिएटिव्यू को कभी भी कॉल नहीं किया गया है। जो कि अजीब तरह का है क्योंकि संपूर्ण व्यूपेजर इसके टुकड़े और इसकी सूची दृश्य के साथ और इसके सेल आइटम सभी तैयार हैं!

मैं # android-देव पर बताया गया था कि एसीएल में ListFragment कस्टम लेआउट का समर्थन नहीं करता तो मैं ListFragment का उपयोग किए बिना फिर से लागू किया मेरी android.support.v4.app.Fragment लेकिन यह मदद नहीं की। देर तक दबाए सेल दबाया में entitiy के बारे में MenuInfo वस्तु युक्त जानकारी बनाने के उद्देश्य के लिए लेआउट मैं जो की घटना को संभालती है एक कस्टम लेआउट है:

संक्षिप्त सारांश। लेआउट में निहित इकाई को खोजने के लिए, listview.getPositionForView(View v) को अंततः बुलाया जाता है, कभी-कभी IllegalStateException का कारण बनता है।

यहाँ मेरी कस्टम लेआउट (शायद वहाँ दृश्य पदानुक्रम में खुदाई से ViewPager की पकड़ पाने के लिए एक आसान तरीका है):

package org.remotestick; 

import android.content.Context; 
import android.support.v4.view.ViewPager; 
import android.util.AttributeSet; 
import android.view.ContextMenu.ContextMenuInfo; 
import android.view.View; 
import android.widget.LinearLayout; 

public class ColumnLayout extends LinearLayout { 

    public ColumnLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public ColumnLayout(Context context) { 
     super(context); 
    } 

    @Override 
    protected ContextMenuInfo getContextMenuInfo() { 
     int itemTypeId = getChildAt(0).getId(); 
     int positionTypeId = getId(); 
     View currentView = this; 
     ViewPager viewPager = null; 
     while(currentView.getParent() != null) { 
      currentView = (View) currentView.getParent(); 
      if(currentView.getId() == R.id.pager) { 
       viewPager = (ViewPager) currentView; 
       break; 
      } else if (currentView.getId() == R.id.rootLayout) 
       break; 
     } 
     if(viewPager == null) 
      return null; 

     WorkspaceAdapter adapter = (WorkspaceAdapter) viewPager.getAdapter(); 
     Pair<Integer, Integer> itemIdAndListPosition = adapter.getItemIdFromWorkspace(viewPager.getCurrentItem(), this, itemTypeId, (positionTypeId == R.id.leftColumn)); 
     if(itemIdAndListPosition == null) 
      return null; 
     else 
      return new MatrixAdaptableContextMenuInfo(itemTypeId, itemIdAndListPosition.first, itemIdAndListPosition.second); 
    } 

    public static class MatrixAdaptableContextMenuInfo implements ContextMenuInfo { 

     public final int itemTypeId; 
     public final Integer itemId; 
     public final Integer positionInList; 

     public MatrixAdaptableContextMenuInfo(int itemTypeId, Integer itemId, Integer positionInList) { 
      this.itemTypeId = itemTypeId; 
      this.itemId = itemId; 
      this.positionInList = positionInList; 
     } 

    } 
} 

और यहाँ (का एक टुकड़ा) Fragment है:

public class EntityTableFragment extends Fragment implements TelldusEntityChangeListener { 

    protected static final String ARG_TITLE = "title"; 

    protected MatrixAdapter mAdapter; 
    protected ProgressViewer mProgressViewer; 
    protected MatrixFilter mFilter; 
    protected Handler mHandler = new Handler(); 
    protected RemoteStickData db; 

    public boolean onAttach = false; 
    public boolean onCreateView = false; 

    private ListView listView; 

    public static EntityTableFragment newInstance(String title) { 
     EntityTableFragment f = new EntityTableFragment(); 

     Bundle args = new Bundle(); 
     args.putString(ARG_TITLE, title); 
     f.setArguments(args); 
     return f; 
    } 

    @Override 
    public void onAttach(SupportActivity activity) { 
     super.onAttach(activity); 
     onAttach = true; 
      try { 
      mProgressViewer = (ProgressViewer) activity; 
      mAdapter = new MatrixAdapter(getActivity(), mProgressViewer, new ArrayList<List<MatrixEntity>>(), null); 
      TelldusLiveService.addListener(this); 
     } catch (ClassCastException e) { 
      throw new ClassCastException(activity.toString() + " must implement ProgressViewer"); 
     } 
     db = new RemoteStickData(getActivity()); 
    } 

    @Override 
    public void onDetach() { 
     super.onDetach(); 
     TelldusLiveService.removeListener(this); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     super.onActivityCreated(savedInstanceState); 
     listView.setAdapter(mAdapter); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 
     View view = inflater.inflate(R.layout.list, null); 
     listView = (ListView) view.findViewById(R.id.list); 
     return view; 
    } 

    @Override 
    public String toString() { 
     return getArguments().getString(ARG_TITLE); 
    } 

    public Pair<Integer, Integer> getIdAndPositionForView(View v, boolean isLeft) { 
     if(listView == null) 
      throw new IllegalStateException("Listview not yet created"); 
     int positionForView = listView.getPositionForView(v); 
     if(isLeft) 
      return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(0).getId(), positionForView); 
     else 
      return new Pair<Integer, Integer>(mAdapter.getItem(positionForView).get(1).getId(), positionForView); 
    } 

क्या यह अजीब बात नहीं है कि, ऐप को फिर से शुरू करने पर (यदि गतिविधि नष्ट हो गई थी), व्यूपेजर इसके टुकड़े और इसकी सूची दृश्य और इसके कस्टम लेआउट के साथ तैयार हैं। फिर भी मुझे IllegalStateException मिल रहा है कि अगर मैं सूचीदृश्य में से किसी भी सेल को लंबे समय से दबाता हूं तो दृश्य नहीं बनाया गया है?

संपादित करें/ वास्तव में, onCreateView में एक Log.d(Constants.TAG, "onCreateView!!!!"); उत्पादन पता चलता है कि तरीकों दो बार पहली बार मैं एप्लिकेशन (ViewPager में प्रत्येक टुकड़ा के लिए एक) शुरू लेकिन तब यह फिर कभी नहीं जब एप्लिकेशन फिर से शुरू है कहा जाता है शुरू हो जाती है! ? क्या यह एक बग है या मैं गलत क्या कर सकता हूं?

उत्तर

4

महत्वपूर्ण हिस्सा FragmentPagerAdapter (जिसे मैंने शामिल नहीं किया) लगता है। डिबगिंग से पता चलता है कि गतिविधि को फिर से बनाया जाने पर getItem() नहीं कहा जाता है। टुकड़े अन्य तरीकों से फिर से बनाए जाते हैं। जिसका अर्थ है कि FragmentPagerAdapter के मेरे कार्यान्वयन में FragmentManager के टुकड़ों के गलत संदर्भ थे।

बजाय, जब मैं एक टुकड़ा मैं findFragmentByTag() का उपयोग करें (FragmentManager पर) makeFragmentName() का उपयोग कर उचित टैग नाम पाने के लिए देखने के लिए की जरूरत है। जब टुकड़ा जोड़ा जाता है तो FragmentPagerAdapter द्वारा उपयोग की जाने वाली विधि है। सुनिश्चित नहीं है कि यह एक सुरक्षित दृष्टिकोण है या नहीं।