source

Android의 컨텍스트에서 작업 가져오기

ittop 2023. 10. 9. 23:32
반응형

Android의 컨텍스트에서 작업 가져오기

이 사람 때문에 곤란해요.

사용자 지정 레이아웃 클래스 내에서 활동 방법을 호출해야 합니다.이 경우의 문제점은 레이아웃 내에서 작업에 액세스하는 방법을 알 수 없다는 것입니다.

종단 뷰

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();
    }
}

프로필 활동

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);
    }
}

위에서 보시는 것처럼 profileView를 프로그램적으로 인스턴스화하고 있습니다. 이와 함께 activityContext를 전달합니다. 2가지 질문:

  1. 프로필 보기에 올바른 컨텍스트를 전달하고 있습니까?
  2. 상황에 맞는 활동을 하려면 어떻게 해야 합니까?

에서.Activity 지나쳐요, thisContext배치에 적합합니다.

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

에 될 것입니다.Context레이아웃에서, 하지만 당신은 그것이 실제로 당신의 것이라는 것을 알 것입니다.Activity필요한 것을 가질 수 있도록 캐스팅할 수 있습니다.

Activity activity = (Activity) context;

가 하는 데 한 것입니다.Context.ActivityUI 내에서 조각 또는 사용자 정의 보기로 작동하는 경우.ContextWrapper를 재귀적으로 풀거나 실패할 경우 null을 반환합니다.

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. 아니요.
  2. 그럴수는 없어요.

안드로이드에는 두 가지 다른 맥락이 있습니다.애플리케이션용(BIG)과 각 보기용(활동 컨텍스트라고 함)을 하나씩 사용합니다.

선형 배치는 보기이므로 활동 컨텍스트를 호출해야 합니다.활동에서 호출하려면 "이것"이라고 부르기만 하면 됩니다.너무 쉽죠?

사용할때

this.getApplicationContext();

애플리케이션을 설명하고 보기를 관리할 수 없는 BIG 컨텍스트를 호출합니다.

Android의 큰 문제는 컨텍스트가 사용자의 활동을 호출할 수 없다는 것입니다.누군가가 안드로이드 개발을 시작할 때 이것을 피하는 것은 대단한 일입니다.클래스를 코드화하는 더 나은 방법을 찾아야 합니다(또는 "Context context"를 "Activity Activity"로 대체하고 필요할 때 "Context"로 캐스트해야 합니다).

안부 전해요.


제 대답을 업데이트하기 위해서입니다. 쉬운 Activity contextA를 정의하는 것입니다.statice에 인스턴스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
}

그리고 코틀린에서:

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

사용자 정의 레이아웃 클래스(비활동 클래스) 내에서 활동 메서드를 호출할 경우.인터페이스를 사용하여 대리인을 만들어야 합니다.

테스트가 되지 않아 제대로 코딩했지만 원하는 것을 이룰 수 있는 방법을 전달합니다.

우선 create and interface

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

컨텍스트는 응용프로그램, 서비스, 활동 등일 수 있습니다.

일반적으로 활동에서 보기의 컨텍스트는 활동 자체이므로 이 컨텍스트를 활동에 캐스팅할 수 있다고 생각할 수 있지만 이 경우 컨텍스트는 ContextTemeWrapper일 수도 있기 때문에 항상 수행할 수는 없습니다.

ContextThemeWrapper는 최근 버전의 AppCompat 및 Android(안드로이드: 레이아웃의 테마 속성 덕분에)에서 많이 사용되므로 개인적으로 이 캐스팅을 수행하지 않을 것입니다.

즉, 보기의 컨텍스트에서 작업을 안정적으로 검색할 수 없습니다.활동을 매개변수로 사용하는 메서드를 호출하여 보기에 활동을 전달합니다.

보기와 함께 getApplicationContext()를 사용하지 마십시오.

보기가 활동에 붙어 있기 때문에 항상 활동의 맥락이 되어야 합니다.또한 사용자 지정 테마 세트가 있을 수 있으며, 응용프로그램 컨텍스트를 사용할 경우 모든 테마가 손실됩니다.여기에서 다양한 버전의 컨텍스트에 대해 자세히 알아보십시오.

Kotlin 사용자의 경우 -

val activity = context as Activity

활동은 컨텍스트의 전문이므로 컨텍스트가 있는 경우 사용할 활동을 이미 알고 있으며 단순히 ac에 캐스팅할 수 있습니다. 여기서 a는 활동이고 c는 컨텍스트입니다.

Activity a = (Activity) c;

Convert Activity를 사용했습니다.

Activity activity = (Activity) context;

나는 이것을(를)

fun Context.findActivity(): Activity? = when (this) {
    is Activity -> this
    is ContextWrapper -> baseContext.findActivity()
    else -> null
}

또는 이 항목:

fun Context.findActivity(): Activity {
    var context = this
    while (context is ContextWrapper) {
        if (context is Activity) return context
        context = context.baseContext
    }
    throw IllegalStateException("no activity")
}

이 방법은 도움이 될 것입니다..!

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;

    }

도움이 되었으면 좋겠습니다.메리코딩!

실시간 데이터 콜백은 어떨까요?

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

class ProfileActivity{

  override fun onCreateView(...){

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

}

확장 함수를 만듭니다.context.getActivity()와 같은 컨텍스트를 사용하여 이 확장 함수를 호출합니다.

fun Context.getActivity(): AppCompatActivity? {
      var currentContext = this
      while (currentContext is ContextWrapper) {
           if (currentContext is AppCompatActivity) {
                return currentContext
           }
           currentContext = currentContext.baseContext
      }
      return null
}

Theo 솔루션의 Kotlin 안드로이드 속기 확장 버전

private fun Context?.getParentActivity() : AppCompatActivity? = when {
    this is ContextWrapper -> if (this is AppCompatActivity) this else this.baseContext.getParentActivity()
    else -> null
}

에서 설명한 용법

언급URL : https://stackoverflow.com/questions/9891360/getting-activity-from-context-in-android

반응형