एडॉप्टर से कॉल गतिविधि विधि


119

क्या उस विधि को कॉल करना संभव है जिसे इसमें परिभाषित किया गया Activityहै ListAdapter?

(मैं पंक्ति Buttonमें एक बनाना चाहता हूं list'sऔर जब यह बटन क्लिक किया जाता है, तो उसे विधि को निष्पादित करना चाहिए, जिसे संबंधित गतिविधि में परिभाषित किया गया है। मैंने onClickListenerअपने में सेट करने की कोशिश की है, ListAdapterलेकिन मुझे नहीं पता कि इस पद्धति को कैसे कॉल किया जाए, इसका रास्ता क्या है। ..)

जब मैंने उपयोग किया तो मुझे Activity.this.method()निम्न त्रुटि मिली:

No enclosing instance of the type Activity is accessible in scope

कोई उपाय ?


जब तक यह गतिविधि का एक आंतरिक वर्ग नहीं है, तब तक आप किसी अन्य कक्षा में गतिविधि को नहीं कह सकते। अपने मामले के लिए @Eldhose M Babu समाधान का पालन करें
Archie.bpgc

जवाबों:


306

हाँ तुम कर सकते हो।

एडेप्टर में एक नया फ़ील्ड जोड़ें:

private Context mContext;

एडेप्टर कन्स्ट्रक्टर में निम्न कोड जोड़ें:

public AdapterName(......, Context context) {
  //your code.
  this.mContext = context;
}

एडाप्टर के getView (...) में:

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
  @Override
  public void onClick(View v) {
    if (mContext instanceof YourActivityName) {
      ((YourActivityName)mContext).yourDesiredMethod();
    }
  }
});

जहाँ आप अपना कोड, अपनी गतिविधि आदि देखते हैं, अपने स्वयं के वर्ग नामों से बदलें

यदि आपको एक से अधिक गतिविधियों के लिए इसी एडाप्टर का उपयोग करने की आवश्यकता है:

एक इंटरफ़ेस बनाएँ

public interface IMethodCaller {
    void yourDesiredMethod();
}

गतिविधियों में इस इंटरफ़ेस को लागू करने के लिए आपको इस पद्धति को कॉल करने की कार्यक्षमता की आवश्यकता होती है।

फिर एडॉप्टर में getView (), जैसे कॉल करें:

Button btn = (Button) convertView.findViewById(yourButtonId);
btn.setOnClickListener(new Button.OnClickListener() {
    @Override
    public void onClick(View v) {
        if (mContext instanceof IMethodCaller) {
            ((IMethodCaller) mContext).yourDesiredMethod();
        }
    }
});

आप कर चुके हैं। यदि आपको इस एडाप्टर को उन गतिविधियों के लिए उपयोग करने की आवश्यकता है जिनके लिए इस कॉलिंग तंत्र की आवश्यकता नहीं है, तो कोड निष्पादित नहीं होगा (यदि चेक विफल रहता है)।


29
जैसा कि यह एक लोकप्रिय प्रश्न है, मैं इस समाधान का उपयोग नहीं करने का दृढ़ता से सुझाव दूंगा। आपको यहां क्लास कास्टिंग से बचना चाहिए, क्योंकि इससे रनटाइम अपवाद हो सकता है।
इगोर फिलिप्पोव

3
एल्डहोस भाई, मेरे पास आपके खिलाफ कुछ भी नहीं है, लेकिन नीचे जवाब सबसे अच्छा अभ्यास है। आप टिप्पणियों में भी पढ़ सकते हैं। आपको अपनी गतिविधि में mContext नहीं डालना चाहिए क्योंकि आप कोड के पुन: उपयोग से बच रहे हैं। अब इस एडॉप्टर का उपयोग केवल उस गतिविधि के अंदर किया जा सकता है, जिसे आपने अपने mContext वैरिएबल में डाला है, जहाँ यदि आपके पास एक श्रोता परिभाषित है तो आप उसी एडेप्टर को किसी अन्य गतिविधि में पुनः उपयोग कर सकते हैं। मेरा विश्वास करो मैंने उद्योग में पर्याप्त समय बिताया है और मैं यहाँ आपकी मदद करने की कोशिश कर रहा हूँ, कृपया इसे व्यक्तिगत रूप से न लें।
वरुंडोइड

2
यह समाधान एसओ पर अब तक का सबसे अच्छा समाधान है। बहुत बहुत धन्यवाद श्री बाबू। इसके द्वारा गतिविधि के तरीकों को कॉल करना, पूरे ऐप को 500% किकिंग प्रदर्शन को बढ़ावा देता है -> मुझे एडेप्टर में डेटाबेस को फिर से लोड करने की आवश्यकता नहीं है, जिसे मुझे एक्सेस करने की आवश्यकता है। मुझे "उद्योग में वर्षों" की परवाह नहीं है, मैं स्थिर और काम कर रहे समाधानों की तलाश कर रहा हूं और मुझे पूरा यकीन है, मुझे पहुंच प्राप्त करने का बेहतर तरीका नहीं मिलेगा। शायद मैं डीबी को एक सिंगलटन के रूप में स्थापित कर सकता था, लेकिन यह वह तरीका नहीं है जो मैं अपनी परियोजना को "अन-स्ट्रक्चर" करना चाहता हूं।
मार्टिन फ़ाफ़र

2
@ राम यदि आपको एक से अधिक गतिविधियों में एक ही विधि को कॉल करने की आवश्यकता है, तो आपको उस विधि नाम के साथ एक इंटरफ़ेस बनाने की आवश्यकता है। फिर उस इंटरफ़ेस को लागू करें जिसमें सभी गतिविधियों में आपको लाभ उठाने के लिए विधि कॉल की आवश्यकता होती है। फिर क्लिक श्रोता में, गतिविधि नाम का उपयोग करने के बजाय अपने इंटरफ़ेस का उदाहरण देखें।
एल्डहोस एम बाबू

1
शानदार जवाब। अंगूठे ऊपर
आलोक राजसुकुमारन

126

आप इसे इस तरह से कर सकते हैं:

डिक्लेयर इंटरफ़ेस:

public interface MyInterface{
    public void foo();
}

अपनी गतिविधि की नकल करें:

public class MyActivity extends Activity implements MyInterface{
    public void foo(){
        //do stuff
    }
}

फिर अपनी गतिविधि को ListAdater को पास करें:

public MyAdapter extends BaseAdater{
    private MyInterface listener;

    public MyAdapter(MyInterface listener){
        this.listener = listener;
    }
}

और एडेप्टर में कहीं, जब आपको उस गतिविधि विधि को कॉल करने की आवश्यकता होती है:

listener.foo();

5
मैंने पहले ऊपर की विधि के बारे में सोचा था जैसे आप टुकड़े करेंगे लेकिन यह सबसे अच्छा समाधान है!
ब्रूक्स

1
जो मेरे इंटरफ़ेसलिस्ट है? इसे कैसे शुरू किया जा सकता है? सार्वजनिक MyAdapter (MyInterface श्रोता) {this.listener = श्रोता; }
गिल्बर्टो इबारा ०

6
आप इंटरफ़ेस को इंटरफ़ेस से कैसे पास करते हैं, हालांकि (गतिविधि से)
ब्रैंडन

1
@ आप इसे पास कर सकते हैं यह एडॉप्टर में कंस्ट्रक्टर पैरामीटर है।
इगोर फिलिप्पोव

5
@Brandon, बस एडैप्टर myAdapter = new MyAdapter (यह) में इंटरफ़ेस पास करने के लिए 'यह' जोड़ें;
अजिंक्य

67

मूल:

मैं वर्तमान उत्तर को समझता हूं लेकिन एक अधिक स्पष्ट उदाहरण की आवश्यकता है। यहाँ एक उदाहरण है जो मैंने एक Adapter(RecyclerView.Adcape) और एक के साथ प्रयोग किया था Activity

आपकी गतिविधि में:

यह लागू होगा interfaceजो हमारे पास है Adapter। इस उदाहरण में, यह तब कहा जाएगा जब उपयोगकर्ता किसी आइटम पर क्लिक करता है RecyclerView

public class MyActivity extends Activity implements AdapterCallback {

    private MyAdapter myAdapter;

    @Override
    public void onMethodCallback() {
       // do something
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        myAdapter = new MyAdapter(this);
    }
}

अपने एडेप्टर में:

में Activity, हमने अपनी पहल की Adapterऔर इसे निर्माणकर्ता के तर्क के रूप में पारित किया। यह interfaceहमारी कॉलबैक पद्धति के लिए पहल करेगा । आप देख सकते हैं कि हम उपयोगकर्ता क्लिक के लिए अपनी कॉलबैक विधि का उपयोग करते हैं।

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private AdapterCallback adapterCallback;

    public MyAdapter(Context context) {
        try {
            adapterCallback = ((AdapterCallback) context);
        } catch (ClassCastException e) {
            throw new ClassCastException("Activity must implement AdapterCallback.", e);
        }
    }

    @Override
    public void onBindViewHolder(MyAdapter.ViewHolder viewHolder, int position) {
        // simple example, call interface here
        // not complete
        viewHolder.itemView.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    adapterCallback.onMethodCallback();
                } catch (ClassCastException e) {
                   // do something
                }
            }
        });
    }

    public static interface AdapterCallback {
        void onMethodCallback();
    }
}

6
इसके लिए धन्यवाद, यह वही है जो मैं देख रहा था। अप-
वोटेड

यह मेरे लिए काम किया! imo, अब तक का सबसे पूर्ण वर्किंग कोड!
युवावली

2
इस समाधान के लिए धन्यवाद
स्टीव

4
इस उत्तर में अधिक अपवित्र होना चाहिए, यह एक स्वच्छ और सही समाधान है।
Opiatefuchs

हाय @ जारेड - EventBusजैसा आपने सुझाव दिया, क्या आप उसी नमूने को सही कर सकते हैं ?
Tohid

15

मूल और सरल।

अपने एडेप्टर में बस इसका उपयोग करें।

((YourParentClass) context).functionToRun();


4
एक अच्छा अभ्यास नहीं है क्योंकि आप अपनी कक्षा को किसी भी वर्ग के बजाय केवल YourParentClass प्रकार के साथ काम करने के लिए प्रतिबंधित कर रहे हैं, लेकिन काम करता है यदि आप इसे पुन: उपयोग करने के बारे में परवाह नहीं करते हैं, यदि आप एक वर्ग कोड का नाम भी बदल देते हैं ...
Gustavo Baiocat Costa

7

एक और तरीका है ::

अपने एडेप्टर में एक विधि लिखें, जो आपको सार्वजनिक शून्य कॉलबैक () {} बताता है।

अब गतिविधि में एडॉप्टर के लिए ऑब्जेक्ट बनाते समय इस विधि को ओवरराइड करें। जब आप एडॉप्टर में विधि कहते हैं तो ओवरराइड विधि को बुलाया जाएगा।

Myadapter adapter = new Myadapter() {
  @Override
  public void callBack() {
    // dosomething
  }
};

5

कोटलिन के लिए:

अपने एडेप्टर में, बस कॉल करें

(context as Your_Activity_Name).yourMethod()

0
if (parent.getContext() instanceof yourActivity) {
  //execute code
}

यह स्थिति आपको कुछ निष्पादित करने में सक्षम करेगी यदि गतिविधि जिसमें आपके GroupViewअनुरोध की getView()विधि से विचार adapterहैyourActivity

नोट: parentवह GroupView है


यह GroupView एडेप्टर से विचारों का अनुरोध करता है जब वह getView()विधि को कॉल करता है ..... तो हम उस GroupView का संदर्भ प्राप्त करते हैं, और इस स्थिति के माध्यम से जांच करते हैं
अब्द सलाम बेकर

0

कोटलिन में अब लैम्ब्डा कार्यों का उपयोग करके एक क्लीनर तरीका है, इंटरफेस की कोई आवश्यकता नहीं है:

class MyAdapter(val adapterOnClick: (Any) -> Unit) {
    fun setItem(item: Any) {
        myButton.setOnClickListener { adapterOnClick(item) }
    }
}

class MyActivity {
    override fun onCreate(savedInstanceState: Bundle?) {
        var myAdapter = MyAdapter { item -> doOnClick(item) }
    }


    fun doOnClick(item: Any) {

    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.