অ্যাডাপ্টারের থেকে ক্রিয়াকলাপ কল করুন


119

এটা সম্ভব পদ্ধতি যে সংজ্ঞায়িত কল হল ActivityথেকেListAdapter ?

(আমি একটি করতে চাই Buttonমধ্যে list'sসারি এবং যখন এই বাটন ক্লিক করা হয়, এটি পদ্ধতি, যে সংশ্লিষ্ট কার্যকলাপে সংজ্ঞায়িত করা হয় সঞ্চালন করা উচিত নয়। আমি সেট করার চেষ্টা করেছিলেন onClickListenerআমার মধ্যে ListAdapterকিন্তু আমি জানি না কিভাবে এই পদ্ধতি, তার পথ কি কল। ..)

যখন আমি ব্যবহার Activity.this.method()করি আমি নিম্নলিখিত ত্রুটিটি পাই:

No enclosing instance of the type Activity is accessible in scope

কোন ধারণা ?


আপনি ক্রিয়াকলাপটিকে কল করতে পারবেন না is এটি অন্য কোনও শ্রেণিতে এই ক্রিয়াকলাপের অভ্যন্তরীণ ক্লাস না থাকলে। আপনার মামলার জন্য @ এল্ডহোজ এম বাবু সমাধান অনুসরণ করুন
আর্কি.বিপিজিসি

উত্তর:


306

হ্যা, তুমি পারো.

অ্যাডাপ্টারে একটি নতুন ক্ষেত্র যুক্ত করুন:

private Context mContext;

অ্যাডাপ্টারের কনস্ট্রাক্টরে নিম্নলিখিত কোড যুক্ত করুন:

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

অ্যাডাপ্টারের গেটভিউ (...) এ:

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
যেহেতু এটি একটি জনপ্রিয় প্রশ্ন, আমি দৃ strongly়ভাবে এই সমাধানটি ব্যবহার না করার পরামর্শ দেব। আপনার এখানে ক্লাস কাস্টিং এড়ানো উচিত, কারণ এটি রানটাইম ব্যতিক্রম হতে পারে।
ইগোর ফিলিপোভ

3
বোধহয় ভাই, আপনার বিরুদ্ধে আমার কিছুই নেই তবে নীচের উত্তরটি সর্বোত্তম অনুশীলন। এমনকি আপনি মন্তব্যগুলিতে পড়তে পারেন। আপনি কোডের পুনরায় ব্যবহার এড়িয়ে যাচ্ছেন তাই আপনার ক্রিয়াকলাপে এমকন্টেক্সট করা উচিত নয়। এখন এই অ্যাডাপ্টারটি কেবলমাত্র আপনার এমকনটেক্সট ভেরিয়েবলটিতে কাস্ট করেছেন এমন ক্রিয়াকলাপের মধ্যেই ব্যবহার করা যেতে পারে, যেখানে আপনার শ্রোতার সংজ্ঞা থাকলে আপনি অন্য ক্রিয়াকলাপে একই অ্যাডাপ্টারটিকে পুনরায় ব্যবহার করতে পারেন। বিশ্বাস করুন আমি শিল্পে যথেষ্ট সময় ব্যয় করেছি এবং আমি এখানে আপনাকে কেবল সাহায্য করার চেষ্টা করছি, দয়া করে এটি ব্যক্তিগতভাবে নেবেন না।
বরুণড্রয়েড

2
এই সমাধানটি আমি এসও-তে সর্বকালের সেরা সন্ধান পেয়েছি। তাই অনেক ধন্যবাদ মিঃ বাবু। এর দ্বারা ক্রিয়াকলাপের পদ্ধতিগুলিকে কল করে পুরো অ্যাপটিকে 500% লাথি মেরে পারফরম্যান্স বাড়িয়ে দেয় -> অ্যাডাপ্টারে আমার ডাটাবেসটি পুনরায় লোড করার দরকার নেই, যা আমার অ্যাক্সেস করতে হবে। আমি "শিল্পের বছরগুলিতে" চিন্তা করি না, আমি স্থিতিশীল এবং কাজের সমাধান খুঁজছি এবং আমি নিশ্চিত যে আমি অ্যাক্সেস পাওয়ার আরও ভাল উপায় খুঁজে পাব না। সম্ভবত আমি সিঙ্গলটন হিসাবে ডিবি সেট আপ করতে পারতাম, তবে আমার প্রকল্পটি "আন-স্ট্রাকচার" করতে চাই না this
মার্টিন ফেফার

2
@ র্যাম যদি আপনার একাধিক ক্রিয়াকলাপে একই পদ্ধতিটি কল করতে হয় তবে আপনাকে সেই পদ্ধতির নামের সাথে একটি ইন্টারফেস তৈরি করতে হবে। তারপরে আপনার যে সমস্ত ক্রিয়াকলাপটি মেথড কলটি গ্রহণ করা প্রয়োজন তা কী সে ক্ষেত্রে সেই ইন্টারফেসটি বাস্তবায়ন করুন। তারপরে ক্লিক শ্রোতার ক্ষেত্রে ক্রিয়াকলাপের নাম ব্যবহার না করে আপনার ইন্টারফেসের উদাহরণটি পরীক্ষা করুন।
এলডহোজ এম বাবু

1
চমত্কার উত্তর।
থাম্বস

126

আপনি এটি এইভাবে করতে পারেন:

ইন্টারফেস ঘোষণা করুন:

public interface MyInterface{
    public void foo();
}

আপনার ক্রিয়াকলাপ এটি কার্যকর করতে দিন:

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

তারপরে আপনার ক্রিয়াকলাপটি তালিকার তালিকায় পাস করুন:

public MyAdapter extends BaseAdater{
    private MyInterface listener;

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

এবং অ্যাডাপ্টারের কোথাও, যখন আপনাকে সেই ক্রিয়াকলাপ পদ্ধতিটি কল করতে হবে:

listener.foo();

5
উপরের পদ্ধতিটি আমি প্রথমে ভেবেছিলাম যেমন আপনি টুকরো টুকরো করে ফেলবেন তবে এটিই সেরা সমাধান!
ব্রুকস

1
আমার ইন্টারফেসলিস্টার কোনটি? কিভাবে এটি সূচনা করতে পারেন? পাবলিক মাইএডাপ্টার (মাইন্টারফেস শ্রোতা) {this.listener = শ্রোতা; }
গিলবার্তো ইবাররা

6
আপনি কীভাবে অ্যাডাপ্টারে ইন্টারফেসটি পাস করবেন (কার্যকলাপ থেকে)
ব্র্যান্ডন

1
@ ব্র্যান্ডন আপনি এটি অ্যাডাপ্টারে কনস্ট্রাক্টর প্যারামিটারটি পাস করতে পারেন।
ইগোর ফিলিপোভ

5
@ ব্র্যান্ডন, মাইএডাপ্টার অ্যাডাপ্টারে ইন্টারফেসটি পাস করার জন্য 'এই' যুক্ত করুন = নতুন মাইএডাপ্টার (এটি);
আজিন্ক্যা

67

মূল:

আমি বর্তমানের উত্তরটি বুঝতে পেরেছি তবে আরও সুস্পষ্ট উদাহরণের প্রয়োজন। এখানে আমি Adapter(রিসাইক্লারভিউ.এডাপ্টার) এবং একটি দিয়ে কী ব্যবহার করেছি তার একটি উদাহরণ 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, এখন পর্যন্ত সবচেয়ে সম্পূর্ণ কাজের কোড!
publicknowledge

2
এই সমাধানের জন্য ধন্যবাদ
স্টিভ

4
এই উত্তরের আরও বেশি উত্স হওয়া উচিত, এটি পরিষ্কার এবং নিখুঁত সমাধান।
Opiatefuchs

হাই @ জ্যারেড - আপনি EventBusযেমন পরামর্শ দিয়েছিলেন তেমন নমুনা ঠিক করতে পারেন ?
তোহিদ

14

বেসিক এবং সহজ।

আপনার অ্যাডাপ্টারে কেবল এটি ব্যবহার করুন।

((YourParentClass) context).functionToRun();


4
একটি ভাল অনুশীলন নয় কারণ আপনি আপনার ক্লাসটিকে কোনও ক্লাসের পরিবর্তে কেবলমাত্র আপনার পিতামাতার শ্রেণীর ধরণের সাথে কাজ করতে সীমাবদ্ধ করছেন, তবে আপনি যদি এটির পুনরায় ব্যবহারের বিষয়ে চিন্তা না করেন তবে কাজ করে, যদি আপনি কোনও শ্রেণীর নামও ভেঙে যায় তবে কোডটি ভেঙে যায় ...
গুস্তাভো বায়োচি কোস্টা

7

আরও একটি উপায় হ'ল ::

আপনার অ্যাডাপ্টারে একটি পদ্ধতি লিখুন যাকে সর্বজনীন শূন্য কলব্যাক () {say বলতে দেয়}

ক্রিয়াকলাপে অ্যাডাপ্টারের জন্য কোনও অবজেক্ট তৈরি করার সময় এই পদ্ধতিটিকে ওভাররাইড করে। যখন আপনি অ্যাডাপ্টারে পদ্ধতিটি কল করবেন তখন ওভাররাইড পদ্ধতিটি কল করা হবে।

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এটি গ্রুপভিউ


এই গ্রুপভিউ অ্যাডাপ্টারের কাছ থেকে মতামতগুলির জন্য অনুরোধ করে যখন এটি getView()পদ্ধতিটি কল করে ..... সুতরাং আমরা সেই গ্রুপভিউয়ের প্রসঙ্গটি পেয়েছি এবং উপরের শর্তের মাধ্যমে এটি পরীক্ষা করি
আবদুল সালাম বাকের

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) {

    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.