在(自定义)view/dialog 内部访问 Activity 的最佳方法?
Best approach to access an Activity on the inside of a (custom) view/dialog?
我的应用程序中只有一个 activity。在我将我的视图和对话框静态存储在 activity 之前,这样我就可以从任何地方访问它们。但我知道这是不好的做法,因为它会导致内存泄漏。
所以我使它们成为非静态的,但现在我需要在视图层次结构的深处引用我的 activity,以访问存储在 activity 中的视图和对话框。
示例:
我的 MainActivity 有一个名为 a
的对话框和一个名为 b
的自定义视图。 b
的onClick方法如何显示对话框a
?
或在代码中:
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
@Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
}
}
public class CustomView extends Button implements OnClickListener {
public CustomView(Context context) {
super(context);
setOnClickListener(this);
}
@Override
public void onClick(View view) {
//wants to show dialog a
MainActivity.a.show(); //Not possible -> a is not static
mainActivity.a.show(); //<-- needs a reference of the activity
// but where from?
}
}
MainActivity mainActivity = (MainActivity) getContext();
将不起作用,因为 getContext() 并不总是 activity 上下文。
更新:
我在下面发布了一个答案!
由于某些原因 Whosebug 只让我在两天内接受我自己的答案
我不知道您的视图层次结构到底是什么样的。
我将您的问题描述为:
Activity A 有一个 recyclerview R,现在 R 中的每个 viewholder H 都应该能够触发 A 中的一些方法。
在这种情况下,将您的 activity 的引用传递给您的 recyclerview 适配器,然后适配器将其传递给 ViewHolder 是可行的。
然后在您的(查看者的)视图的 onClick 方法中使用它。
在这里,您可以使用“回调”模式。在 Whosebug 上有很多关于这个的帖子,例如here.
所以实施步骤是:
- 定义接口
- 让您的 activity 实现该接口
- 让您的适配器将接口作为构造函数参数并传递给您activity。 (在这个例子中:你必须用你的 viewHolder 重复这个步骤,从适配器传递接口)
- 在 onClick 方法中使用此接口方法 -> 然后这将触发您的活动方法
实现取决于实际层次结构。如果您的其他视图在片段中,那么您也可以使用(共享)ViewModel。
根据你的图片,我首先想到的是 callback-pattern 方法。
您可以在 MainActivity 中覆盖 onClick; class 定义本身可能不需要这样做。
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
@Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
a.show();
}
});
}
}
这是 android 中非常常见的模式,我不知道您的视图层次结构是什么样的,但在大多数情况下它应该有效。
我无法理解为什么 class 扩展 Button
需要实现 View.OnClickListener
。在活动中创建侦听器或让 MainActivity
实施 OnClickListener
.
更有意义
几分钟后这里就有一个答案被证明是正确的。
我不知道作者为什么删除它,但它有一个 link 到 答案:
private static Activity unwrap(Context context) {
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (Activity) context;
}
因此,每次您需要 activity 时,您只需调用 Activity activity = unwrap(getContext());
。
我不知道它是否真的打算这样做,或者它是否是一种解决方法,但它确实起作用了(至少在我的情况下)。
我的应用程序中只有一个 activity。在我将我的视图和对话框静态存储在 activity 之前,这样我就可以从任何地方访问它们。但我知道这是不好的做法,因为它会导致内存泄漏。
所以我使它们成为非静态的,但现在我需要在视图层次结构的深处引用我的 activity,以访问存储在 activity 中的视图和对话框。
示例:
我的 MainActivity 有一个名为 a
的对话框和一个名为 b
的自定义视图。 b
的onClick方法如何显示对话框a
?
或在代码中:
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
@Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
}
}
public class CustomView extends Button implements OnClickListener {
public CustomView(Context context) {
super(context);
setOnClickListener(this);
}
@Override
public void onClick(View view) {
//wants to show dialog a
MainActivity.a.show(); //Not possible -> a is not static
mainActivity.a.show(); //<-- needs a reference of the activity
// but where from?
}
}
MainActivity mainActivity = (MainActivity) getContext();
将不起作用,因为 getContext() 并不总是 activity 上下文。
更新:
我在下面发布了一个答案! 由于某些原因 Whosebug 只让我在两天内接受我自己的答案
我不知道您的视图层次结构到底是什么样的。
我将您的问题描述为: Activity A 有一个 recyclerview R,现在 R 中的每个 viewholder H 都应该能够触发 A 中的一些方法。
在这种情况下,将您的 activity 的引用传递给您的 recyclerview 适配器,然后适配器将其传递给 ViewHolder 是可行的。 然后在您的(查看者的)视图的 onClick 方法中使用它。 在这里,您可以使用“回调”模式。在 Whosebug 上有很多关于这个的帖子,例如here.
所以实施步骤是:
- 定义接口
- 让您的 activity 实现该接口
- 让您的适配器将接口作为构造函数参数并传递给您activity。 (在这个例子中:你必须用你的 viewHolder 重复这个步骤,从适配器传递接口)
- 在 onClick 方法中使用此接口方法 -> 然后这将触发您的活动方法
实现取决于实际层次结构。如果您的其他视图在片段中,那么您也可以使用(共享)ViewModel。 根据你的图片,我首先想到的是 callback-pattern 方法。
您可以在 MainActivity 中覆盖 onClick; class 定义本身可能不需要这样做。
public class MainActivity extends Activity {
private CustomDialog a;
private CustomView b;
@Override
protected void onCreate(Bundle savedInstanceState) {
a = new CustomDialog(this);
b = new CustomView(this);
b.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
a.show();
}
});
}
}
这是 android 中非常常见的模式,我不知道您的视图层次结构是什么样的,但在大多数情况下它应该有效。
我无法理解为什么 class 扩展 Button
需要实现 View.OnClickListener
。在活动中创建侦听器或让 MainActivity
实施 OnClickListener
.
几分钟后这里就有一个答案被证明是正确的。
我不知道作者为什么删除它,但它有一个 link 到
private static Activity unwrap(Context context) {
while (!(context instanceof Activity) && context instanceof ContextWrapper) {
context = ((ContextWrapper) context).getBaseContext();
}
return (Activity) context;
}
因此,每次您需要 activity 时,您只需调用 Activity activity = unwrap(getContext());
。
我不知道它是否真的打算这样做,或者它是否是一种解决方法,但它确实起作用了(至少在我的情况下)。