8

同じタスクの別のスレッドにオブジェクトを送信する必要があるだけなのに、なぜオブジェクトをパーセルする必要があるのですか? 実際には、同じスレッド (メイン スレッド) でも実行されるアクティビティを開く必要があります。

言い換えれば、なぜ Google はバンドルの代わりにジェネリック オブジェクトの広告パラメーターを使用するバージョンの startActivity を提供しなかったのかということです。スレッド(メインスレッド)?

4

5 に答える 5

12

あるアクティビティから別のアクティビティにオブジェクトを渡すために Parcelable を使用する必要はありません。次のように、オブジェクトへの参照を静的メンバー変数に格納するだけです。

public class Globals {
     public static MyObject myObject;
}

さて、オブジェクトを持つコードでは、次のことを行うだけです。

Globals.myObject = object;

新しいアクティビティでは、次のように取得できます。

doSomethingWith(Globals.myObject);

さて、そうは言っても、次のことに注意する必要があります。

アプリケーションがバックグラウンドにある場合、Android はいつでもプロセスを強制終了できます。その後、ユーザーがアプリケーションに戻ると、Android はアプリケーション用の新しいプロセスを作成し、アクティビティ スタックの一番上にあったアクティビティ(つまり、表示されていたアクティビティ) のみを再作成します。Globals.myObjectその場合、新しく作成されたアクティビティは、プロセスが新しく作成され、そのメンバー変数が null であるため、アクセスして iobject を取得できません。

これを回避するには、次のいずれかを実行できます。

  1. プロセスが強制終了され、再起動されたことを確認します (チェックGlobals.myObject == nullしてそれに応じて対応する - ユーザーに戻る必要があることを伝えるか、自分で戻るか、ダイアログなどを表示するかを伝えます)
  2. アクティビティでAndroid が呼び出されたときにオブジェクトを保存しonSaveInstanceState()(アプリをバックグラウンドに送信する前に Android が実行します)、オブジェクトを復元します。onCreate()

うまくいけば、これがあなたの質問に答え、それについて何をすべきかを説明します。

編集: インテントにオブジェクト自体ではなく、シリアル化された (Parcelable) オブジェクトが含まれる理由に関する詳細情報を追加します

  1. startActivity()またはAndroidを呼び出すとstartService()、別のプロセスでアクティビティまたはサービスが開始される場合があります。この場合、インテントでオブジェクトを渡した場合、Android は何らかの方法でそのオブジェクトをシリアル化して他のプロセスに渡す必要があります。どのコンポーネントが Intent を処理するかを決定するために Android が使用する「暗黙の Intent 解決」のため、呼び出し元は、どのコンポーネントが開始されるかを認識している場合と認識していない場合があります。

  2. Android は、さまざまな理由でインテントの内容を保存します。

    A. Android はいつでもプロセスを強制終了できます。それが行われ、ユーザーがアプリケーションに戻りたい場合、Android は新しいプロセスを作成し、必要に応じてそのプロセスでアクティビティを再作成します。アクティビティを作成するには、Android でインテントをアクティビティで使用できるようにする必要もあります。プロセスが強制終了された場合、インテント内のすべての「オブジェクト」を保存して復元する必要があります。インテントにはシリアル化されたオブジェクトが含まれているため、必要に応じてこれらを再作成しても問題ありません。B. PendingIntents は、オペレーティング システムが Intent の送信者のプロキシとして機能する方法として、Android によって使用されます。Android コンポーネントは PendingIntent を作成し、それをオペレーティング システムに渡して、後でその Intent の送信をトリガーできるようにします。送信コンポーネントは、PendingIntent が実際に送信される時点でアクティブである場合とアクティブではない場合があります。つまり、呼び出し元のコンポーネントが存在しなくなった場合でも Android がオブジェクトを保持できるように、PendingIntent で渡すことができるオブジェクトはすべてシリアル化できる必要があります。

  3. インテントは、コンポーネント間の一般的な「パラメータ受け渡し」メカニズムとして意図されたものではありません。もちろん、そのように使用することもできますが、他の (より簡単な) メカニズムを使用することもできます。特定のプロセス内で、標準の Java メカニズムを使用してオブジェクトを渡すことができます。これに静的 (クラス) 変数を使用しても問題はありません。

于 2012-09-04T15:15:55.500 に答える
4

Android の公式ドキュメント (FAQ 内) には、複雑なデータ構造を渡す方法に関する多くの情報が記載されています。

単一のアプリケーション内のアクティビティ/サービス間でデータを渡すにはどうすればよいですか? http://developer.android.com/guide/faq/framework.html#3

プリミティブ データ型

アプリケーション内のアクティビティ/サービス間でプリミティブ データを共有するには、Intent.putExtras() を使用します。保持する必要があるプリミティブ データを渡すには、Preferences ストレージ メカニズムを使用します。非永続オブジェクト

複雑で非永続的なユーザー定義オブジェクトを短期間共有するには、次のアプローチが推奨されます。

シングルトンクラス

シングルトンを使用すると、アプリケーション コンポーネントが同じプロセスで実行されるという事実を利用できます。これは、インスタンスを 1 つだけ持つように設計されたクラスです。インスタンスを返す getInstance() などの名前の静的メソッドがあります。このメソッドが初めて呼び出されたときに、グローバル インスタンスが作成されます。すべての呼び出し元が同じインスタンスを取得するため、これを対話のポイントとして使用できます。たとえば、アクティビティ A はインスタンスを取得して setValue(3) を呼び出します。後でアクティビティ B がインスタンスを取得し、getValue() を呼び出して、最後に設定された値を取得する場合があります。

public static フィールド/メソッド

アクティビティ/サービス間でデータにアクセスできるようにする別の方法は、パブリックな静的フィールドおよび/またはメソッドを使用することです。これらの静的フィールドには、アプリケーション内の他のクラスからアクセスできます。オブジェクトを共有するには、オブジェクトを作成するアクティビティがこのオブジェクトを指すように静的フィールドを設定し、このオブジェクトを使用する他のアクティビティはこの静的フィールドにアクセスするだけです。

オブジェクトへの WeakReferences の HashMap

長いキーを持つオブジェクトへの WeakReferences の HashMap を使用することもできます。アクティビティがオブジェクトを別のアクティビティに渡したいときは、単にオブジェクトをマップに配置し、キー (カウンターまたはタイム スタンプに基づく一意の Long) をインテント エクストラを介して受信者のアクティビティに送信します。受信者アクティビティは、このキーを使用してオブジェクトを取得します。

永続オブジェクト

アプリケーションが実行を続けているように見えても、システムはそのプロセスを強制終了し、後で再起動することを選択する場合があります。あるアクティビティの呼び出しから次の呼び出しまで保持する必要があるデータがある場合、そのデータは、アクティビティがなくなる可能性があると通知されたときにアクティビティによって保存される状態として表す必要があります。

複雑で永続的なユーザー定義オブジェクトを共有するには、次のアプローチが推奨されます。

- Application Preferences
- Files
- contentProviders
- SQLite DB

アプリケーション プロセスを強制終了できるポイント間で共有データを保持する必要がある場合は、そのデータをアプリケーション設定、SQLite DB、ファイル、または ContentProvider などの永続ストレージに配置します。これらのコンポーネントの使用方法の詳細については、データ ストレージを参照してください。

これが必要な理由:

これは、Android の独自のマルチタスク機能とコンポーネント ライフサイクルの考え方によるものです。ユーザーがアプリを離れることができるようにするために (アクティビティ A、B、および C、およびインテント i1、i2、i3 など)、システムはアプリケーションをコンポーネントに分割します。

そうすれば、ユーザーがインテント i2 を使用してアクティビティ B を起動しても、電話がかかってきたり、メールをチェックしたりした場合、ユーザーはアクティビティ B に戻ることができ、Android システムはインテント i2 を再配信できます。また、ユーザーはアプリで中断したところから簡単かつシームレスに再開できます。

コンポーネントのライフサイクルを使用すると、個々のコンポーネントへの入り口と出口がはるかに簡単になります。BroadcastReceiversまた、 、 、Servicesなどの異なるタイプのコンポーネント間の非同期通信も可能ですActivities

これを行うために、OS は「マーシャリング」と呼ばれるものを実行します。データをプリミティブ データ型 ( や など)にフラット化して、簡単にメモリに保持したり、後で取得するために一時ストレージに書き込んだりできるようにします。 intchar

さらに、これはあらゆるタイプの IPC (プロセス間通信) に必要です。

を使用するIntentと、開発者は Android OS にマーシャリングを実行させることができます。これは、通常は面倒です (そして、困難またはバグが発生する可能性があります)。

于 2012-09-11T18:15:12.613 に答える
2

Android では、タスク、アクティビティ、スレッド、またはサービス間で渡すすべてのオブジェクトを、Parcelまたは implementにフラット化する必要がありますSerializable。これにより、オブジェクトを値で渡すことができます。オブジェクトをメソッドまたは関数に渡すときは、参照渡しです。インテントがシステムに渡され、インテントがアクティビティの 1 つを開始するか、別のアプリを開くかなど、インテントのルーティング先がシステムによって決定されます。

受信オブジェクトがアプリの一部ではない場合、受信側はアプリのメモリにアクセスできません。そのため、オブジェクト参照を渡すと、受信側のアプリがクラッシュする可能性がありました。オブジェクトを Parcel または Serializable BLOB にフラット化することで、受信者は元の参照にアクセスすることなく、送信された値を操作できます。基本的なオブジェクトを渡すことができる機能を Google が実装する場合、すべてのオブジェクトに対してディープ コピー関数を作成する必要があり、すべてのカスタム オブジェクトに対してディープ コピー関数を作成する必要があり、非常に面倒で遅くなります。 VM をオーバーフローさせる可能性のあるかなりの量のシステム メモリを占有します。オブジェクトを渡すための共通の基本的な機能を提供することで、パフォーマンスを高速化し、メモリ要件を削減し、

ただし、前に述べたように、すべてがアプリケーションの一部である限り、アクティビティ間で渡したいオブジェクトへのグローバル参照を作成できます。これは最も洗練された解決策ではなく、不要なメモリを食い尽くさないように参照を使い終わったときに参照を無効にする必要がありますが、十分に機能します。

于 2012-09-11T16:57:44.193 に答える
1

すべてのアクティビティは、UIスレッドでのみ実行を作成します。他に方法はありません。オブジェクトを分割する必要性についての質問に関しては、実際にはそれが唯一の方法ではありません。オブジェクトにSerializableインターフェースも実装させることで、オブジェクトを渡すことができます。

大まかに言えば、インテントは、アクティビティ、サービス、ブロードキャストレシーバーなどのさまざまなコンポーネント間で通信するための非同期メッセージングメカニズムです。ソースと宛先のコンポーネントは同じアプリケーション(したがってプロセス)の一部である場合とそうでない場合があり、Androidフレームワークでは、必要に応じてプロセス間でオブジェクトを渡す標準化された方法が必要です。

于 2012-09-04T13:43:35.217 に答える
-3

アクティビティ/サービスなどの間でカスタムクラスオブジェクトを渡すため。Bundle内で使用する場合、クラスはまたはIntentを実装する必要があります。ParcelableSerializable

これが、プッシュする前にオブジェクトを分割する必要がある理由です。Bundle

于 2012-09-04T13:42:15.873 に答える