いくつかのアクティビティを参照する必要があるメソッドにアクセスする必要があることに気付くことがよくあります。たとえば、を使用するgetWindowManager
には、いくつかのアクティビティにアクセスする必要があります。しかし、これらのメソッドを使用するための私のコードは、アクティビティへの参照を持たない他のクラスにあることがよくあります。これまで、メインアクティビティへの参照を保存するか、一部のアクティビティのコンテキストをクラスに渡しました。これを行うためのより良い方法はありますか?
12 に答える
コンテキストを渡すことは、アクティビティを参照するためのより良い方法です。
Context を別のクラスに渡すことができます。
IN アクティビティ ::
AnotherClass Obj = new AnotherClass(this);
別のクラスで
class AnotherClass{
public AnotherClass(Context Context){
}
}
アクティビティに必要なメソッドを実装し、Handlerを実装できます。次に、ハンドラ インスタンスをクラスに渡すだけで、ハンドラのメッセージを取得してターゲットに送信できます。
アプリケーションインスタンスをシングルトンにして、コンテキストが必要なときに使用できます
例はこの質問にあります:
シングルトンとしての Android アプリケーション
このように、コンテキストが必要な場合は、次の方法で取得できます
Context context = MyApplication.getInstance()
これは最もクリーンなソリューションではないかもしれませんが、これまでのところうまくいきました
私は android を初めて使用するので、私の提案はばかげているように見えるかもしれませんが、アクティビティへの参照をプライベート プロパティとして作成し、それを OnCreate メソッドに割り当てるとどうなるでしょうか? そのような OnCreate を使用して CustomActivity を作成し、adnroid によって提供される一般的な Activity ではなく、CustomActivity からすべてのアクティビティを派生させることもできます。
class blah extends Activity{
private Activity activityReference;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activityReference = this;
}
}
Intent i = new Intent(activityReference, SomeOtherActivity.class)
等
そのためのフレームワークを構築しました。BaseActivity
から継承し、すべてのライフサイクル メソッドをオーバーライドするActivity
クラスがあり、アクティビティ スタックを追跡するいくつかの静的 (クラス) 変数があります。現在のアクティビティが何であるかを知りたい場合は、静的メソッドを呼び出すだけBaseActivity
で、プライベートに管理されたスタックの一番上にアクティビティが返されます。
ちょっとハックですが、動作します。私はそれをお勧めするかどうかはわかりません。
アクティビティのコミュニケーションには多くの方法があります。
あなたが使用することができます:
startActivityForResult メソッド
ブロードキャスト メッセージとレシーバーのシステム (実際のアクティビティからイベントをブロードキャストし、ターゲット アクティビティにレシーバーを登録できます。ターゲット アクティビティは事前に初期化され、未完了である必要があることに注意してください)
- あなたが言うように、必要な場所にターゲットアクティビティの参照を保存してください。
これらのメソッドを実行するクラスでインテントを処理し、次のようにバンドルで情報を送信します。
Intent i = new Intent("android.intent.action.MAIN");
i.setComponent(new ComponentName("com.my.pkg","com.my.pkg.myActivity"));
Bundle data = new Bundle();
i.putExtras(data);
startActivityForResult(i);
次に、OnActivityResultListener を使用して新しいデータを取得します。
シングルトンクラスに以下のクラスのインスタンスをメンバーとして持たせることでこれを解決しました。
public class InterActivityReferrer <T> {
HashMap<Integer, T> map;
ArrayList<Integer> reserve;
public InterActivityReferrer() {
map = new HashMap<>();
reserve = new ArrayList<>();
}
public synchronized int attach(T obj) {
int id;
if (reserve.isEmpty()) {
id = reserve.size();
}
else {
id = reserve.remove(reserve.size() - 1);
}
map.put(id, obj);
return id;
}
public synchronized T get(int id) {
return map.get(id);
}
public synchronized T detach(int id) {
T obj = map.remove(id);
if (obj != null) reserve.add(id);
return obj;
}
}
このクラスは、T オブジェクトを取得し、attach() によってオブジェクトに割り当てられた一意の整数を返すことができます。HashMap が失敗しない限り、割り当てられた整数は互いに衝突しません。割り当てられた各整数は、対応するオブジェクトが detach() によってデタッチされると解放されます。解放された整数は、新しいオブジェクトがアタッチされたときに再利用されます。
そしてシングルトンクラスから:
public class SomeSingleton {
...
private InterActivityReferrer<Activity> referrer = new InterActivityReferrer<>();
...
public InterActivityReferrer<Activity> getReferrer() {return referrer;}
}
そして、参照する必要があるアクティビティから:
...
int activityID = SomeSingleton.getInstance().getReferrer().attach(this);
...
これで、このアクティビティ インスタンスに対応する一意の整数が返されます。また、Intent と putExtra() を使用して、別の開始アクティビティに整数を渡すことができます。
...
Intent i = new Intent(this, AnotherActivity.class);
i.putExtra("thisActivityID", activityID);
startActivityForResult(i, SOME_INTEGER);
...
そして別の活動から:
...
id refereeID = getIntent().getIntExtra("thisActivityID", -1);
Activity referredActivity = SomeSingleton.getInstance().getReferrer().get(refereeID);
...
最後に、アクティビティを参照できます。また、InterActivityReferrer は他のどのクラスにも使用できます。
これが役立つことを願っています。
public static Activity getLaunchActivity()
{
final Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
final Method methodApp = activityThreadClass.getMethod("currentApplication");
App = (Application) methodApp.invoke(null, (Object[]) null);
Intent launcherIntent = App.getPackageManager().getLaunchIntentForPackage(App.getPackageName());
launchActivityInfo = launcherIntent.resolveActivityInfo(App.getPackageManager(), 0);
Class<?> clazz;
try
{
clazz = Class.forName(launchActivityInfo.name);
if(clazz != null)
return Activity.class.cast(clazz.newInstance());
}
catch (Exception e)
{}
return null;
}
やったことがないので推測ですが、うまくいくかもしれません。
1) Android アプリケーション クラスをシングルトンにして、applicationContext を取得します。
2) コンテキストから ActivityManager クラスを取得します。
3) ActivityManager で getRunningTasks() を使用して、RunningTaskInfos のリストを取得します。
4) リストから最初の RunningTaskInfo 要素を取得します。これは、起動された最新のタスクです。
5) その RunningTaskInfo で topActivity を呼び出します。これにより、そのタスクのアクティビティ スタックのトップ アクティビティが返されます。
これは、ここで言及した他のどのメソッドよりも多くの作業のように思えますが、おそらくこれを静的クラスにカプセル化して、いつでも呼び出すことができます。アクティビティへの参照を追加せずにスタックのトップ アクティビティを取得する唯一の方法のようです。