অ্যান্ড্রয়েডে প্রসঙ্গ থেকে ক্রিয়াকলাপ পাওয়া


182

এই এক আমার তুলবেন হয়েছে।

কাস্টম বিন্যাস শ্রেণীর মধ্যে থেকে আমাকে একটি ক্রিয়াকলাপ পদ্ধতি কল করতে হবে। এটির সাথে সমস্যাটি হ'ল লেআউটটির মধ্য থেকে কীভাবে কার্যকলাপটি অ্যাক্সেস করতে হয় তা আমি জানি না।

ProfileView

public class ProfileView extends LinearLayout
{
    TextView profileTitleTextView;
    ImageView profileScreenImageButton;
    boolean isEmpty;
    ProfileData data;
    String name;

    public ProfileView(Context context, AttributeSet attrs, String name, final ProfileData profileData)
    {
        super(context, attrs);
        ......
        ......
    }

    //Heres where things get complicated
    public void onClick(View v)
    {
        //Need to get the parent activity and call its method.
        ProfileActivity x = (ProfileActivity) context;
        x.activityMethod();
    }
}

ProfileActivity

public class ProfileActivityActivity extends Activity
{
    //In here I am creating multiple ProfileViews and adding them to the activity dynamically.

    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.profile_activity_main);
    }

    public void addProfilesToThisView()
    {
        ProfileData tempPd = new tempPd(.....)
        Context actvitiyContext = this.getApplicationContext();
        //Profile view needs context, null, name and a profileData
        ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
        profileLayout.addView(pv);
    }
}

আপনি উপরের দেখতে পাচ্ছেন, আমি প্রোফাইল ভিউটিকে প্রোগ্রামটিমেটিকভাবে ইনস্ট্যান্ট করছি এবং এটির সাথে ক্রিয়াকলাপে প্রেরণ করছি। 2 টি প্রশ্ন:

  1. আমি কি প্রোফাইল ভিউতে সঠিক প্রসঙ্গটি পার করছি?
  2. আমি কীভাবে প্রাসঙ্গিক থেকে ক্রিয়াকলাপটি পেতে পারি?

উত্তর:


471

আপনার থেকে Activityশুধু মধ্যে পাস thisহিসাবে Contextআপনার লেআউট জন্য:

ProfileView pv = new ProfileView(this, null, temp, tempPd);

এর পরে আপনার Contextবিন্যাসে একটি থাকবে তবে আপনি জানতে পারবেন এটি আসলে আপনার Activityএবং আপনি এটি কাস্ট করতে পারেন যাতে আপনার যা প্রয়োজন তা হয়:

Activity activity = (Activity) context;

53
আপনার গ্যারান্টি দেওয়া যায় না যে আপনি যে প্রসঙ্গে কাজ করছেন সেটি হ'ল একটি কার্যকলাপ প্রসঙ্গ বা অ্যাপ্লিকেশন প্রসঙ্গে। একটি ডায়ালগভিউতে একটি অ্যাপ্লিকেশন প্রসঙ্গটি পাস করার চেষ্টা করুন, এটি ক্র্যাশ করুন এবং আপনি পার্থক্যটি দেখতে পাবেন।
স্কাই কেলসি

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

6
দ্রষ্টব্য যে 'এই' এর পরিবর্তে 'getApplicationContext ()' কাজ করবে না।
dwbrito

1
@ বোরিসস্ট্রান্ডজেভ আপনার মন্তব্যটি আমি যথেষ্ট বুঝতে পারি নি। যাইহোক, আমি বলেছি যে আপনার উদাহরণটি চেষ্টা করার পরে কিন্তু 'এটি' এর পরিবর্তে আমি getapplicationContext () ব্যবহার করেছি এবং অ্যাপ্লিকেশনটি নিজেই অ্যাপটিকে কাস্ট করার চেষ্টা করেছিল, সুতরাং ক্রিয়াকলাপের পরিবর্তে একটি কাস্ট ত্রুটি দিয়েছে। 'এই' এ স্যুইচ করার পরে, যেমন আপনি উত্তর দিয়েছেন, এটি কার্যকর হয়েছে।
dwbrito

1
আপনার লিঙ্কে সর্বাধিক উত্সাহিত উত্তর উভয়ই যদি এটি গন্ধযুক্ত হয় তবে প্রশ্নটিকে চ্যালেঞ্জ জানানোর পরামর্শ দেয়। এই প্রশ্ন অবশ্যই দুর্গন্ধযুক্ত। ওপি প্রথমে বলেছিল: "আমাকে কাস্টম বিন্যাস শ্রেণীর মধ্যে থেকে একটি ক্রিয়াকলাপ পদ্ধতি কল করা দরকার।" যা ইন্টারফেসের যথাযথ ব্যবহারের সাথে সম্পূর্ণরূপে অর্জনযোগ্য। তারপরে তিনি বলেন "এটির সাথে সমস্যাটি হ'ল আমি জানিনা কীভাবে বিন্যাসের মধ্যে থেকে ক্রিয়াকলাপটি অ্যাক্সেস করতে হয়।" যা একটি ভুল বোঝাবুঝির প্রতি তাৎপর্যপূর্ণ ইঙ্গিত। প্রোগ্রামিংয়ে লোকেরা সমস্ত সময় ভুল কাজটি করার চেষ্টা করে এবং আমাদের এটির দিকে দৃষ্টি দেওয়া উচিত নয়।
স্যাম

39

এটি এমন কিছু যা আমি সফলভাবে ইউআই এর মধ্যে টুকরোগুলি বা কাস্টম ভিউগুলিতে রূপান্তর Contextকরতে রূপান্তর করতে ব্যবহার করেছি Activity। এটি ContextWrapper পুনরাবৃত্তভাবে আনপ্যাক করবে বা ব্যর্থ হলে শূন্য ফিরে আসবে।

public Activity getActivity(Context context)
{
    if (context == null)
    {
        return null;
    }
    else if (context instanceof ContextWrapper)
    {
        if (context instanceof Activity)
        {
            return (Activity) context;
        }
        else
        {
            return getActivity(((ContextWrapper) context).getBaseContext());
        }
    }

    return null;
}

এটি সঠিক উত্তর। অন্যগুলি সামগ্রী বিষয়বস্তু শ্রেণিবিন্যাসকে বিবেচনা করে না।
স্নিকোলাস

এটিই আসল উত্তর :)
লিজস্টেট

1
@lygstate: আপনি আপনার অ্যাপটিতে কোন টার্গেটের এপিআই স্তরটি ব্যবহার করছেন? ত্রুটি কী? এটি কেবলমাত্র ইউআই-এর মধ্যে কাজ করে (ক্রিয়াকলাপ, টুকরা ইত্যাদি), পরিষেবাগুলিতে নয়।
থিও

31
  1. না
  2. আপনি পারবেন না

অ্যান্ড্রয়েডে দুটি ভিন্ন প্রসঙ্গ রয়েছে। আপনার অ্যাপ্লিকেশনের জন্য একটি (আসুন একে বিজি বলা যাক) এবং প্রতিটি দর্শনের জন্য একটি (আসুন এটি ক্রিয়াকলাপের প্রসঙ্গে বলি)।

লিনিয়ারলআউট একটি দৃশ্য, তাই আপনাকে ক্রিয়াকলাপের প্রসঙ্গে কল করতে হবে। কোনও ক্রিয়াকলাপ থেকে এটিকে কল করতে, কেবল "এটি" কল করুন। এত সহজ তাই না?

আপনি যখন ব্যবহার

this.getApplicationContext();

আপনি বিআইজি প্রসঙ্গকে কল করুন, আপনার অ্যাপ্লিকেশনটির বর্ণনা দেয় এবং আপনার দৃশ্য পরিচালনা করতে পারে না।

অ্যান্ড্রয়েডের সাথে একটি বড় সমস্যা হ'ল একটি প্রসঙ্গ আপনার ক্রিয়াকলাপটিকে কল করতে পারে না। যখন কেউ অ্যান্ড্রয়েড বিকাশ দিয়ে শুরু করেন এটি এড়ানোর জন্য এটি একটি বড় বিষয়। আপনার ক্লাসে কোড দেওয়ার আরও ভাল উপায় খুঁজে বের করতে হবে (বা "কার্যকলাপের ক্রিয়াকলাপ" দ্বারা "প্রসঙ্গের প্রসঙ্গ" প্রতিস্থাপন করতে হবে এবং যখন প্রয়োজন হবে তখন এটি "প্রসঙ্গ" এ কাস্ট করতে হবে)।

শুভেচ্ছা।


শুধু আমার উত্তর আপডেট করতে। আপনার পাওয়ার সহজতম উপায় Activity contextহ'ল staticআপনার মধ্যে কোনও উদাহরণ সংজ্ঞায়িত করা Activity। উদাহরণ স্বরূপ

public class DummyActivity extends Activity
{
    public static DummyActivity instance = null;

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

        // Do some operations here
    }

    @Override
    public void onResume()
    {
        super.onResume();
        instance = this;
    }

    @Override
    public void onPause()
    {
        super.onPause();
        instance = null;
    }
}

এবং তারপর, আপনার Task, Dialog, View, আপনি যে ধরনের কোডের আপনার পেতে ব্যবহার করতে পারে Activity context:

if (DummyActivity.instance != null)
{
    // Do your operations with DummyActivity.instance
}

4
2 টি বিভিন্ন ধরণের প্রসঙ্গের মধ্যে বিভ্রান্তির একটি খুব সাধারণ ক্ষেত্রটি ব্যাখ্যা করার জন্য +1 (ঠিক যেমন 2 টি আলাদা আলাদা রয়েছে R)। গুগল লোকেরা তাদের শব্দভান্ডার সমৃদ্ধ করা প্রয়োজন।
an00b

3
বিটিডাব্লু, @ বরিসস্ট্রান্ডজেভ সঠিক: ২ হ্যাঁ আপনি পারবেন । (কাজের কোড নিয়ে তর্ক করতে পারে না)
an00b

2
2. সত্যই নয়। প্রসঙ্গটি যদি অ্যাপ্লিকেশন প্রসঙ্গ হয় তবে আপনার অ্যাপ্লিকেশনটি ক্রাশ হবে।
স্ট্যাক ওভারফ্লো হয়েছে

স্থির উদাহরণ ?! @ নেপস্টারের এই ইমোটির সর্বোত্তম সমাধান রয়েছে
স্যাম

14
কোনও ক্রিয়াকলাপের স্থিতিশীল রেফারেন্স তৈরি করা মেমরি ফুটো তৈরির সেরা উপায়।
ব্লেডকডার

8

আপনি যদি কাস্টম বিন্যাস শ্রেণীর (অ-ক্রিয়াকলাপ শ্রেণি) মধ্যে থেকে কোনও ক্রিয়াকলাপ পদ্ধতি কল করতে চান তবে আপনার ইন্টারফেস ব্যবহার করে একটি প্রতিনিধি তৈরি করা উচিত।

এটি অপরিবর্তিত এবং আমি এটি ঠিক কোড করেছিলাম। তবে আপনি যা চান তা অর্জন করার জন্য আমি একটি উপায় অবহিত করছি।

সবার আগে তৈরি এবং ইন্টারফেস

interface TaskCompleteListener<T> {
   public void onProfileClicked(T result);
}



public class ProfileView extends LinearLayout
{
    private TaskCompleteListener<String> callback;
    TextView profileTitleTextView;
    ImageView profileScreenImageButton;
    boolean isEmpty;
    ProfileData data;
    String name;

    public ProfileView(Context context, AttributeSet attrs, String name, final ProfileData profileData)
    {
        super(context, attrs);
        ......
        ......
    }
    public setCallBack( TaskCompleteListener<String> cb) 
    {
      this.callback = cb;
    }
    //Heres where things get complicated
    public void onClick(View v)
    {
        callback.onProfileClicked("Pass your result or any type");
    }
}

এবং এটিকে যে কোনও ক্রিয়াকলাপে প্রয়োগ করুন।

এবং এটি পছন্দ করুন

ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
pv.setCallBack(new TaskCompleteListener
               {
                   public void onProfileClicked(String resultStringFromProfileView){}
               });

1
এটি সঠিক উত্তর এবং সঠিক উত্তর হিসাবে চিহ্নিত করা উচিত। আমি জানি সঠিক হিসাবে চিহ্নিত উত্তরটি আসলে ওপির প্রশ্নের উত্তর দেয়, তবে এটির মতো প্রশ্নের উত্তর দেওয়া উচিত নয়। আসল বিষয়টি হ'ল ভিউটির মতো ক্রিয়াকলাপে পাস করা ভাল অনুশীলন নয়। সন্তানের মাধ্যমে কোনও ক্ষেত্রেই তাদের পিতামাতার সম্পর্কে জানা উচিত নয় Context। নেপস্টার বলেছেন যে, সেরা অনুশীলন হ'ল কলব্যাকটি পাস করা, সুতরাং যখনই পিতামাতার আগ্রহের কিছু ঘটে তখন প্রাসঙ্গিক ডেটা দিয়ে কলব্যাকটি সরিয়ে দেওয়া হবে।
দারউইন্ড

6

প্রসঙ্গটি কোনও অ্যাপ্লিকেশন, একটি পরিষেবা, একটি ক্রিয়াকলাপ এবং আরও অনেক কিছু হতে পারে।

সাধারণত কোনও ক্রিয়াকলাপে দর্শনগুলির প্রসঙ্গটি হ'ল ক্রিয়াকলাপ তাই আপনার মনে হতে পারে আপনি কেবলমাত্র এই প্রসঙ্গে ক্রিয়াকলাপে প্রচ্ছন্ন কাস্ট করতে পারেন তবে বাস্তবে আপনি এটি সর্বদা এটি করতে পারবেন না, কারণ এই ক্ষেত্রে প্রসঙ্গটিও একটি ContextThemeWrapper হতে পারে।

ContextThemeWrapper অ্যাপকম্প্যাট এবং অ্যান্ড্রয়েডের সাম্প্রতিক সংস্করণগুলিতে ভারী ব্যবহৃত হয় (অ্যান্ড্রয়েডের জন্য ধন্যবাদ: বিন্যাসে থিম বৈশিষ্ট্য) তবে আমি ব্যক্তিগতভাবে কখনও এই কাস্ট অভিনয় করতে পারব না।

এত সংক্ষিপ্ত উত্তর হ'ল: আপনি কোনও দৃশ্যের প্রসঙ্গ থেকে নির্ভরযোগ্যতার সাথে একটি ক্রিয়াকলাপ পুনরুদ্ধার করতে পারবেন না। ক্রিয়াকলাপটিকে প্যারামিটার হিসাবে গ্রহণ করে এমন কোনও পদ্ধতিতে কল করে দর্শনে কার্যকলাপটি পাস করুন।


3

কখনই getApplicationContext () ব্যবহার করবেন নাভিউ সহ ।

ক্রিয়াকলাপের সাথে দৃশ্যটি সংযুক্ত থাকায় এটি সর্বদা ক্রিয়াকলাপের প্রসঙ্গ হওয়া উচিত। এছাড়াও, আপনার কাছে একটি কাস্টম থিম সেট থাকতে পারে এবং অ্যাপ্লিকেশনের প্রসঙ্গটি ব্যবহার করার সময়, সমস্তগুলি হারাতে হবে। প্রেক্ষিতে বিভিন্ন সংস্করণ সম্পর্কে আরও পড়ুন এখানে


3

এবং কোটলিনে:

tailrec fun Context.activity(): Activity? = when {
  this is Activity -> this
  else -> (this as? ContextWrapper)?.baseContext?.activity()
}

0

একটি কার্যকলাপ, কনটেক্সট একটি বিশেষায়িত রূপ যাতে আপনি আপনার কনটেক্সট আপনি ইতিমধ্যে জানেন যা কার্যকলাপ আপনি ব্যবহার করতে মনস্থ কেবল কাস্ট করতে পারেন আছে যদি একটি মধ্যে ; যেখানে a হল একটি ক্রিয়াকলাপ এবং সি একটি প্রসঙ্গ।

Activity a = (Activity) c;

7
এটি বিপজ্জনক কারণ পৃথক মন্তব্যে যেমন উল্লেখ করা হয়েছে, প্রসঙ্গটি সর্বদা একটি ক্রিয়াকলাপ নাও হতে পারে।

4
টাইপকাস্ট কেবলমাত্র (কার্যকলাপের প্রসঙ্গে) {// টাইপকাস্ট}
অমিত যাদব

0

আমি ক্রিয়াকলাপ ক্রিয়াকলাপ ব্যবহার করেছি

Activity activity = (Activity) context;

2
বিভিন্ন ধরণের প্রসঙ্গ আছে। ক্রিয়াকলাপ এবং অ্যাপ্লিকেশনগুলির প্রসঙ্গ থাকতে পারে। এটি কেবল তখনই কাজ করবে যখন প্রসঙ্গটি কোনও ক্রিয়াকলাপের হয়।
সাইলোভ

0

এই পদ্ধতিটি সাহায্য করা উচিত ..!

public Activity getActivityByContext(Context context){

if(context == null){
    return null;
    }

else if((context instanceof ContextWrapper) && (context instanceof Activity)){
        return (Activity) context;
    }

else if(context instanceof ContextWrapper){
        return getActivity(((ContextWrapper) context).getBaseContext());
    }

return null;

    }

আমি আশা করি এটি সাহায্য করে .. মেরি কোডিং!


আপনি যে প্রসঙ্গটি পাস করেছেন তা শূন্য নয় কিনা পরীক্ষা করুন .. সম্ভবত সমস্যাটিই সম্ভবত।
তাসলিম ওসেনি

0

কিছু লাইভ ডেটা কলব্যাক সম্পর্কে কীভাবে,

class ProfileView{
    private val _profileViewClicked = MutableLiveData<ProfileView>()
    val profileViewClicked: LiveData<ProfileView> = _profileViewClicked
}

class ProfileActivity{

  override fun onCreateView(...){

    profileViewClicked.observe(viewLifecycleOwner, Observer { 
       activityMethod()
    })
  }

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