2011-10-25 113 views
1

我已經閱讀了很多關於如何使用Parcel的文章,並且在我的應用中使用過它,但它不起作用。我剛剛創建了一個活動,您可以使用Sockets連接到計算機。我在Socket的OutputStream上打開java.io.PrintWriter,我想要另一個活動(在第一個活動中觸摸按鈕時打開)使用相同的PrintWriter。我認爲我在這裏犯的錯誤不是克隆PrintWriter object。我不知道如何克隆它。Android:難以將一個對象從一個活動傳遞到另一個活動使用Parcel

這裏的第一個活動(我已經去除了一些不必要的功能):

public class TestActivity extends Activity implements OnClickListener 
{ 
    String ip; 
    int port; 
    Socket soc; 
    PrintWriter writer; // this works fine here 

    @Override 
    public void onCreate(Bundle savedInstanceState) 
    { 
     ip = ""; 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     // Connect button click handler (you can skip this part) 
     Button connect = (Button)findViewById(R.id.connectBTN); 
     connect.setOnClickListener(new View.OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       EditText TB = (EditText)findViewById(R.id.ipTB); 
       ip = TB.getText().toString(); 
       TB = (EditText)findViewById(R.id.portTB); 
       port = Integer.parseInt(TB.getText().toString()); 
       try { 
       soc = new Socket(ip,port); 
       showDialog("Connected successfully!"); 
       writer = new PrintWriter(soc.getOutputStream(), true); 
       } 
       catch(Exception er) 
       { 
        showDialog("Couldn't connect.\n"+er.getMessage()); 
        soc = null; 
       } 
      } 
     }); 

     findViewById(R.id.controlmouseBTN).setOnClickListener(this); 

     // disconnect click handler (skip this part too) 
     Button disconnectBTN = (Button)findViewById(R.id.disconnectBTN); 
     disconnectBTN.setOnClickListener(new View.OnClickListener() 
     { 
      public void onClick(View v) 
      { 
       try 
       { 
        if(soc.isConnected()) soc.close(); 
        writer.close(); 
       } 
       catch(Exception er) { showDialog("Couldn't close connection.\n"+er.getMessage()); } 
      } 
     }); 

    } 

    @Override 
    public void onClick(View v) // here is the erroneous part 
    { 
     //if(soc == null || !soc.isConnected()) { showDialog("Not connected to any computer."); return; } 
     //if(writer == null) return; 
     Intent i = new Intent(getApplicationContext(), PCController.class); 
     Intermediate inter = new Intermediate(); // this is the Parcelable class I've created 
     //inter.set(new String("hello")); (I tried sending a string, which worked fine, just to confirm that my Parcelable class is working) 
     inter.set(writer); 
     i.putExtra("printer", inter); 
     startActivity(i); 
    } 

} 

這裏是Parcelable類中級

import android.os.*; 

public class Intermediate implements Parcelable 
{ 
    Object ob; 

    public Intermediate() 
    {} 

    public Intermediate(Parcel parcel) 
    { 
     this.ob = parcel.readValue(Intermediate.class.getClassLoader()); 
    } 

    public void set(Object o) 
    { this.ob = o; } 

    public Object get() 
    { 
     return ob; 
    } 

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

    @Override 
    public void writeToParcel(Parcel dest, int flags) 
    { 
     dest.writeValue(this.ob); 
    } 

    // I don't understand this part though! Just copy pasted and modified the ClassName 

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

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

下面的代碼的下一個活動的是代碼被解僱。 (我已經張貼只有必不可少的一部分)

PrintWriter writer; 
    String s; // for testing purpose 
    Swipe swipe; // a SurfaceView 

    public void onCreate(Bundle bundle) 
    { 
     super.onCreate(bundle); 
     swipe = new Swipe(this); 
     swipe.setOnTouchListener(this); 
     setContentView(swipe); 
     Intent i = getIntent(); 
     Intermediate ob = (Intermediate)i.getParcelableExtra("printer"); 
     writer = (PrintWriter)ob.get(); 
     //s = (String)ob.get(); 
     //showDialog(s); // this shows up the string I had sent, which means the string is getting passed. 
    } 

現在,當我不連接(即writer爲空),我開始了下一個活動,沒有任何反應(沒有錯誤)。 但是,當我連接(writer不爲空),我開始下一個活動,主要活動只是崩潰。我沒有打擾記錄錯誤信息,因爲我知道我在這裏做了一些非常錯誤的事情。

任何幫助,將不勝感激!謝謝!

編輯:這裏是異常堆棧跟蹤

10-26 00:37:55.445: WARN/System.err(251): java.lang.RuntimeException: Parcel: unable to marshal value [email protected] 
10-26 00:37:55.474: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1087) 
10-26 00:37:55.484: WARN/System.err(251):  at android.test.Intermediate.writeToParcel(Intermediate.java:33) 
10-26 00:37:55.484: WARN/System.err(251):  at android.os.Parcel.writeParcelable(Parcel.java:1106) 
10-26 00:37:55.494: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1029) 
10-26 00:37:55.504: WARN/System.err(251):  at android.os.Parcel.writeMapInternal(Parcel.java:469) 
10-26 00:37:55.514: WARN/System.err(251):  at android.os.Bundle.writeToParcel(Bundle.java:1445) 
10-26 00:37:55.524: WARN/System.err(251):  at android.os.Parcel.writeBundle(Parcel.java:483) 
10-26 00:37:55.534: WARN/System.err(251):  at android.content.Intent.writeToParcel(Intent.java:5237) 
10-26 00:37:55.544: WARN/System.err(251):  at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1204) 
10-26 00:37:55.554: WARN/System.err(251):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1373) 
10-26 00:37:55.564: WARN/System.err(251):  at android.app.Activity.startActivityForResult(Activity.java:2749) 
10-26 00:37:55.574: WARN/System.err(251):  at android.app.Activity.startActivity(Activity.java:2855) 
10-26 00:37:55.584: WARN/System.err(251):  at android.test.TestActivity.onClick(TestActivity.java:80) 
10-26 00:37:55.594: WARN/System.err(251):  at android.view.View.performClick(View.java:2364) 
10-26 00:37:55.606: WARN/System.err(251):  at android.view.View.onTouchEvent(View.java:4179) 
10-26 00:37:55.615: WARN/System.err(251):  at android.widget.TextView.onTouchEvent(TextView.java:6541) 
10-26 00:37:55.624: WARN/System.err(251):  at android.view.View.dispatchTouchEvent(View.java:3709) 
10-26 00:37:55.634: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.634: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.644: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.656: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:37:55.664: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659) 
10-26 00:37:55.674: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107) 
10-26 00:37:55.684: WARN/System.err(251):  at android.app.Activity.dispatchTouchEvent(Activity.java:2061) 
10-26 00:37:55.694: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643) 
10-26 00:37:55.705: WARN/System.err(251):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1691) 
10-26 00:37:55.714: WARN/System.err(251):  at android.os.Handler.dispatchMessage(Handler.java:99) 
10-26 00:37:55.724: WARN/System.err(251):  at android.os.Looper.loop(Looper.java:123) 
10-26 00:37:55.734: WARN/System.err(251):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
10-26 00:37:55.744: WARN/System.err(251):  at java.lang.reflect.Method.invokeNative(Native Method) 
10-26 00:37:55.754: WARN/System.err(251):  at java.lang.reflect.Method.invoke(Method.java:521) 
10-26 00:37:55.764: WARN/System.err(251):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
10-26 00:37:55.774: WARN/System.err(251):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
10-26 00:37:55.785: WARN/System.err(251):  at dalvik.system.NativeStart.main(Native Method) 
10-26 00:38:02.424: WARN/System.err(251): java.lang.RuntimeException: Parcel: unable to marshal value [email protected] 
10-26 00:38:02.454: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1087) 
10-26 00:38:02.454: WARN/System.err(251):  at android.test.Intermediate.writeToParcel(Intermediate.java:33) 
10-26 00:38:02.464: WARN/System.err(251):  at android.os.Parcel.writeParcelable(Parcel.java:1106) 
10-26 00:38:02.474: WARN/System.err(251):  at android.os.Parcel.writeValue(Parcel.java:1029) 
10-26 00:38:02.486: WARN/System.err(251):  at android.os.Parcel.writeMapInternal(Parcel.java:469) 
10-26 00:38:02.494: WARN/System.err(251):  at android.os.Bundle.writeToParcel(Bundle.java:1445) 
10-26 00:38:02.505: WARN/System.err(251):  at android.os.Parcel.writeBundle(Parcel.java:483) 
10-26 00:38:02.514: WARN/System.err(251):  at android.content.Intent.writeToParcel(Intent.java:5237) 
10-26 00:38:02.524: WARN/System.err(251):  at android.app.ActivityManagerProxy.startActivity(ActivityManagerNative.java:1204) 
10-26 00:38:02.534: WARN/System.err(251):  at android.app.Instrumentation.execStartActivity(Instrumentation.java:1373) 
10-26 00:38:02.544: WARN/System.err(251):  at android.app.Activity.startActivityForResult(Activity.java:2749) 
10-26 00:38:02.554: WARN/System.err(251):  at android.app.Activity.startActivity(Activity.java:2855) 
10-26 00:38:02.554: WARN/System.err(251):  at android.test.TestActivity.onClick(TestActivity.java:80) 
10-26 00:38:02.564: WARN/System.err(251):  at android.view.View.performClick(View.java:2364) 
10-26 00:38:02.574: WARN/System.err(251):  at android.view.View.onTouchEvent(View.java:4179) 
10-26 00:38:02.584: WARN/System.err(251):  at android.widget.TextView.onTouchEvent(TextView.java:6541) 
10-26 00:38:02.594: WARN/System.err(251):  at android.view.View.dispatchTouchEvent(View.java:3709) 
10-26 00:38:02.604: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.614: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.625: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.634: WARN/System.err(251):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:884) 
10-26 00:38:02.644: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1659) 
10-26 00:38:02.654: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1107) 
10-26 00:38:02.664: WARN/System.err(251):  at android.app.Activity.dispatchTouchEvent(Activity.java:2061) 
10-26 00:38:02.674: WARN/System.err(251):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1643) 
10-26 00:38:02.684: WARN/System.err(251):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1691) 
10-26 00:38:02.694: WARN/System.err(251):  at android.os.Handler.dispatchMessage(Handler.java:99) 
10-26 00:38:02.704: WARN/System.err(251):  at android.os.Looper.loop(Looper.java:123) 
10-26 00:38:02.714: WARN/System.err(251):  at android.app.ActivityThread.main(ActivityThread.java:4363) 
10-26 00:38:02.714: WARN/System.err(251):  at java.lang.reflect.Method.invokeNative(Native Method) 
10-26 00:38:02.724: WARN/System.err(251):  at java.lang.reflect.Method.invoke(Method.java:521) 
10-26 00:38:02.734: WARN/System.err(251):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 
10-26 00:38:02.744: WARN/System.err(251):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 
10-26 00:38:02.754: WARN/System.err(251):  at dalvik.system.NativeStart.main(Native Method) 
+0

發佈異常堆棧跟蹤可能有助於深入瞭解問題。 – Craigy

+0

好吧,我會這樣做 – Rushil

+1

看着最頂層的異常,它似乎不能馬歇爾價值或東西。 – Rushil

回答

3

您在這裏有一個更大的問題。您不應該使用Parcels在活動之間傳遞內容。根據android文檔:

包裹不是通用序列化機制。該類(以及用於將任意對象放入Parcel的相應Parcelable API)被設計爲高性能IPC傳輸。因此,將任何Parcel數據放入持久性存儲中是不恰當的:Parcel中任何數據的底層實現中的更改都會導致舊數據無法讀取。

您應該使用包。我通常做的是在類中創建兩個靜態方法,我試圖在稱爲toBundle和fromBundle的活動之間傳遞。 toBundle接收我想要傳輸的類的實例並返回一個包。 fromBunle接受一個包並返回該類的一個實例。

我不知道有任何方法可以在活動之間傳遞像PrintWriter這樣的複雜對象。但是,您的代碼還存在其他問題。你在主UI線程上做網絡資源。這會導致你的應用凍結很多。您需要將所有IO都移至不同的線程。這很好,因爲那樣你就可以將所有IO的東西移動到可以從兩個活動中訪問的獨立類中。例如,使用IntentService。這將使您的應用程序sooooooo好得多。您可能還想閱讀文章Painless Threading。這是一個關鍵的閱讀,我建議所有的Android開發人員。

+0

你能否通過發佈真實的代碼來解釋一點?我不知道如何傳遞PrintWriter對象。 – Rushil

+0

更具體地說,你如何「捆綁」一個對象? Bundle似乎沒有任何方法可以用來包裝類的實例。 – Rushil

+0

Rushil,這是正確的。您無法捆綁PrintWritter。我已經擴大了我的答案來解決這個問題。 –

0

您無法使用任何常規的Android數據傳遞方法(Bundles/Parcels)在兩個Android活動之間傳遞PrintWriter。如果您必須在兩個活動之間共享PrintWriter,則可以使用靜態變量。

這就是說,你也可以編寫一個服務,你可以訪問和使用每個活動。您可能需要查看ApiDemos項目中的LocalService示例,以獲取有關如何執行此操作的示例。網上也有無數的教程。

相關問題