13

アクティビティからリモートサービスに渡すために使用するParcelableオブジェクトがあります。AIDLインターフェースを使用して渡すと、すべてが正常に聞こえます。

最近、 ActivityからMessengerを通過させようとしています。

// TEST TEST TEST!
StockInfo stockInfo0 = new StockInfo(Code.newInstance("code0"), Symbol.newInstance("symbol0"));
StockInfo stockInfo1 = new StockInfo(Code.newInstance("code1"), Symbol.newInstance("symbol1"));
StockInfo stockInfo2 = new StockInfo(Code.newInstance("code2"), Symbol.newInstance("symbol2"));
List<StockInfo> stockInfos = new ArrayList<StockInfo>();
stockInfos.add(stockInfo0);
stockInfos.add(stockInfo1);
stockInfos.add(stockInfo2);
StockInfosEx stockInfosEx = new StockInfosEx(stockInfos, "abc");
msg.obj = stockInfosEx;

try {
    mService.send(msg);
} catch (RemoteException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

リモートサービスで次の例外が発生します。

02-21 22:55:16.546:E / Parcel(8365):アンマーシャリング時にクラスが見つかりません:com.example.testonmessenger.StockInfosEx、e:java.lang.ClassNotFoundException:com.example.testonmessenger.StockInfosEx

私は疑問に思っていました、その間に何がうまくいかないのですか?これが私のParcelableオブジェクトです。

public class StockInfosEx implements Parcelable {
    public final List<StockInfo> stockInfos;
    public final String searchedString;

    public StockInfosEx(List<StockInfo> stockInfos, String searchedString) {
        this.stockInfos = stockInfos;
        this.searchedString = searchedString;
    }

    ////////////////////////////////////////////////////////////////////////////
    // Handling Parcelable nicely.

    public static final Parcelable.Creator<StockInfosEx> CREATOR = new Parcelable.Creator<StockInfosEx>() {
        public StockInfosEx createFromParcel(Parcel in) {
            return new StockInfosEx(in);
        }

        public StockInfosEx[] newArray(int size) {
            return new StockInfosEx[size];
        }
    };

    private StockInfosEx(Parcel in) {
        stockInfos = new ArrayList<StockInfo>();
        in.readTypedList(stockInfos, StockInfo.CREATOR);
        searchedString = in.readString();
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel parcel, int flags) {
        parcel.writeTypedList(stockInfos);
        parcel.writeString(searchedString);
    }

    // Handling Parcelable nicely.    
    ////////////////////////////////////////////////////////////////////////////        
}

完全なソースコードを入手するには、https: //www.dropbox.com/s/n69yuhddpb8vedz/testonmessenger.zipからダウンロードしてください。

4

3 に答える 3

23

実行不可能なアプローチ(Parcelableはカスタムであり、Rectのようなフレームワークの一部ではないため)

アクティビティ

msg.obj = stockInfosEx;

リモートサービス

StockInfosEx stockInfosEx = (StockInfosEx)msg.obj;

実行可能なアプローチ

アクティビティ

msg.getData().putParcelable("data", stockInfosEx);

リモートサービス

msg.getData().setClassLoader(StockInfosEx.class.getClassLoader());
StockInfosEx stockInfosEx = (StockInfosEx)msg.getData().getParcelable("data");

さて、msg.obj(http://developer.android.com/reference/android/os/Message.html#obj)のドキュメントをもう一度読み返した後、それが実際に何を意味するのかを理解したのは私だけです。Parcelable of a framework class

受信者に送信する任意のオブジェクト。Messengerを使用してプロセス間でメッセージを送信する場合、これは、フレームワーククラスのParcelable(アプリケーションによって実装されたものではない)が含まれている場合にのみnull以外になります。その他のデータ転送には、setData(Bundle)を使用します。

ここでのパーセル可能なオブジェクトは、FROYOリリースより前ではサポートされていないことに注意してください。

于 2013-02-21T16:36:28.363 に答える
6

おそらく正しいものを使用していませんClassLoaderClassLoaderそもそもクラスをマーシャリングしているものを追跡し、それを使用ClassLoaderしてマーシャリングを解除する必要があります。

マーシャリングを解除するときは、現在のスレッドのClassLoaderを使用しています。これは、UIThreadではなくAndroidシステムスレッドであるため、カスタムクラスに関する情報はありません。

私はこれを解決するために自分を含む静的クラスを使用しましたClassLoader(静的でなくても同様のアプローチを使用できます)。

何かのようなもの:

ClassLoaderHelper.setClassLoader(Thread.currentThread().getContextClassLoader());

次に、マーシャリングを解除する場合:

public final void readFromParcel(final Parcel in) {
    id = in.readString();
    appInfo = in.readParcelable(ClassLoaderHelper.getClassLoader());
    ...
}

詳細については、この他の質問を参照してください(おそらく重複しています)。

于 2013-02-21T15:32:24.283 に答える
3

リモートサービスで次の例外が発生します。

これを本当にリモートサービスから取得しているのは、リモートサービスアプリにそのクラスが含まれていないためです。カスタムクラスを使用する場合はParcelable、クライアントとサーバーの両方で同じクラス定義を使用する必要があります。

ただし、スタックトレースがコアOSプロセスからアクセスされているように感じられる場合は、オブジェクトを確実にParcelable渡すことができません。私はこれまで、プロセス内のオブジェクトの受け渡しにのみ使用し、プロセス間のメッセージには使用していません。ParcelableobjobjMessage

于 2013-02-21T15:40:22.413 に答える