Dieser hat mich verblüfft.
Ich muss eine Aktivitätsmethode aus einer benutzerdefinierten Layoutklasse aufrufen. Das Problem dabei ist, dass ich nicht weiß, wie ich vom Layout aus auf die Aktivität zugreifen kann.
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);
}
}
Wie Sie oben sehen können, instantiiere ich die profileView programmatisch und gebe den ActivityContext damit weiter. 2 Fragen:
Übergeben Sie in Ihrer Activity
einfach this
als Context
für Ihr Layout:
ProfileView pv = new ProfileView(this, null, temp, tempPd);
Danach haben Sie eine Context
im Layout, aber Sie wissen, dass es sich tatsächlich um Ihre Activity
handelt, und Sie können sie so umsetzen, dass Sie das bekommen, was Sie brauchen:
Activity activity = (Activity) context;
Es gibt zwei verschiedene Kontexte in Android. Eine für Ihre Anwendung (nennen wir sie die GROSSE) und eine für jede Ansicht (nennen wir sie den Aktivitätskontext).
Ein lineares Layout ist eine Ansicht, daher müssen Sie den Aktivitätskontext aufrufen. Um von einer Aktivität aus aufzurufen, rufen Sie einfach "this" auf. So einfach ist es nicht?
Wenn Sie verwenden
this.getApplicationContext();
Sie rufen den BIG-Kontext auf, der Ihre Anwendung beschreibt, und können Ihre Ansicht nicht verwalten.
Ein großes Problem bei Android ist, dass ein Kontext Ihre Aktivität nicht aufrufen kann. Das ist eine große Sache, um dies zu vermeiden, wenn jemand mit der Android-Entwicklung beginnt. Sie müssen einen besseren Weg finden, Ihre Klasse zu codieren (oder "Kontextkontext" durch "Aktivitätsaktivität" ersetzen und bei Bedarf in "Kontext" umwandeln).
Grüße.
Nur um meine Antwort zu aktualisieren. Der einfachste Weg, Ihren Activity context
zu erhalten, besteht darin, eine static
-Instanz in Ihrer Activity
zu definieren. Zum Beispiel
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;
}
}
Und dann könnten Sie in Ihrer Task
, Dialog
, View
diesen Code verwenden, um Ihren Activity context
zu erhalten:
if (DummyActivity.instance != null)
{
// Do your operations with DummyActivity.instance
}
Dies ist etwas, das ich erfolgreich verwendet habe, um Context
in Activity
zu konvertieren, wenn ich innerhalb der Benutzeroberfläche in Fragmenten oder benutzerdefinierten Ansichten arbeite. Es wird ContextWrapper rekursiv entpackt oder zurückgegeben, wenn es fehlschlägt.
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;
}
Wenn Sie eine Aktivitätsmethode innerhalb einer benutzerdefinierten Layoutklasse (Nicht-Aktivitätsklasse) aufrufen möchten. Sie sollten einen Delegaten mithilfe der Schnittstelle erstellen.
Es ist nicht getestet und ich habe es richtig codiert. aber ich vermittle einen Weg, um das zu erreichen, was Sie wollen.
Zunächst einmal erstellen und 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");
}
}
Und implementiere dies für jede Aktivität.
und nennen es gerne
ProfileView pv = new ProfileView(actvitiyContext, null, temp, tempPd);
pv.setCallBack(new TaskCompleteListener
{
public void onProfileClicked(String resultStringFromProfileView){}
});
Der Kontext kann eine Anwendung, ein Dienst, eine Aktivität und mehr sein.
Normalerweise ist der Kontext von Ansichten in einer Aktivität die Aktivität selbst. Sie denken also, dass Sie diesen Kontext einfach in Aktivität umwandeln können, aber Sie können dies nicht immer tun, da der Kontext in diesem Fall auch ein ContextThemeWrapper sein kann.
ContextThemeWrapper wird in den letzten Versionen von AppCompat und Android stark verwendet (dank des Attributs Android: theme in Layouts). Daher würde ich diesen Cast niemals persönlich durchführen.
Die Antwort ist kurz: Sie können eine Aktivität nicht zuverlässig aus einem Kontext in einer Ansicht abrufen. Übergeben Sie die Aktivität an die Ansicht, indem Sie eine Methode für die Ansicht aufrufen, die die Aktivität als Parameter übernimmt.
Verwenden Sie niemals getApplicationContext () mit Ansichten.
Es sollte immer der Kontext der Aktivität sein, da die Sicht an die Aktivität gebunden ist. Möglicherweise haben Sie auch ein benutzerdefiniertes Design, und wenn Sie den Anwendungskontext verwenden, gehen alle Themen verloren. Lesen Sie mehr über verschiedene Versionen von Kontexten hier .
Und in Kotlin:
tailrec fun Context.activity(): Activity? = when {
this is Activity -> this
else -> (this as? ContextWrapper)?.baseContext?.activity()
}
Ich habe convert Activity verwendet
Activity activity = (Activity) context;
Diese Methode sollte hilfreich sein ..!
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;
}
Ich hoffe das hilft. Fröhliche Kodierung!
eine Aktivität ist eine Spezialisierung von Kontext. Wenn Sie also einen Kontext haben, wissen Sie bereits, welche Aktivität Sie verwenden möchten, und Sie können a in c; Dabei ist a eine Aktivität und c ein Kontext.
Activity a = (Activity) c;