0

我想將一個窗體生成到我的activity_main.xml ScrollView中。 XML被正確加載和解析,但是當我試圖添加View(LinearLayout)時,它會拋出異常e。我的應用程序通過推送通知獲取XML文件的URL,然後解析它。根據XML,它應該生成一個表單並將其顯示給用戶。我用這個作爲一個例子:https://www.ibm.com/developerworks/xml/tutorials/x-andddyntut/#l1來自XML的動態android窗體

這是我的主要活動:

public class MainActivity extends Activity { 
// label to display gcm messages 
TextView lblMessage; 
Controller aController; 
public ScrollView sv; 
Button execute; 

// Asyntask 
AsyncTask<Void, Void, Void> mRegisterTask; 

public static String name; 
public static String email; 

final Context context = this; 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    ScrollView sv = (ScrollView) findViewById(R.id.sv); 

... 
} 

// Create a broadcast receiver to get message and show on screen 
private final BroadcastReceiver mHandleMessageReceiver = new BroadcastReceiver() { 

    @Override 
    public void onReceive(Context context, Intent intent) { 

     String newMessage = intent.getExtras().getString(Config.EXTRA_MESSAGE); 

     // Waking up mobile if it is sleeping 
     aController.acquireWakeLock(getApplicationContext()); 

     ScrollView sv = (ScrollView) findViewById(R.id.sv); 
     new DoInBackground(getApplicationContext(), sv).execute(newMessage); 

     // Releasing wake lock 
     aController.releaseWakeLock(); 

    } 
}; 

,這裏是我的異步類:

public class DoInBackground extends AsyncTask<String, Void, Void> { 

Context mContext; 
ScrollView mSv; 

String tag = "DynamicFormXML"; 
XmlGuiForm theForm; 
ProgressDialog progressDialog; 
Handler progressHandler; 

public DoInBackground(Context context, ScrollView sv) { 

    this.mContext = context; 
    this.mSv = sv; 
} 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 

} 

@Override 
protected Void doInBackground(String... params) { 

    if (GetFormData(params[0])) { 
     DisplayForm(); 
    } 
    else 
    { 
     Log.e(tag,"Couldn't parse the Form."); 
     AlertDialog.Builder bd = new AlertDialog.Builder(mContext); 
     AlertDialog ad = bd.create(); 
     ad.setTitle("Error"); 
     ad.setMessage("Could not parse the Form data"); 
     ad.show(); 

    } 
    return null; 
} 


protected void onPostExecute() { 

} 

private boolean DisplayForm() 
{ 

    try 
    {   
     final LinearLayout ll = new LinearLayout(mContext); 
     mSv.addView(ll); //Here it fails 
     ll.setOrientation(android.widget.LinearLayout.VERTICAL); 
... 
    } catch (Exception e) { // Goes to here 
     Log.e(tag,"Error Displaying Form"); 
     return false; 
    } 
} 

我認爲主要活動的背景下,也是主活動中的空滾動視圖正確轉發(它們不是空),但我不是100%確定。任何幫助/提示表示讚賞! :)

回答

1

您不能從後臺線程(例如運行doInBackground方法的那個)觸摸GUI。

AsynTask中,您可以將UI代碼放入onPostExecute,在UI線程上調用該代碼,結果爲doInBackground

如果你有,你可以從doInBackground調用publishProgress中間結果,這將觸發UI線程,在那裏你可以更新UI上的onProgressUpdate調用。

查看AsyncTask API的一個例子和關於哪些線程必須完成的更多細節。

0

解決方案

重新排序的代碼(所以GUI的東西會做onPostExecute)工作。另外我有一個問題沒有得到onPostExecute(),但我不得不將其更改爲onPostExecute(Void結果)。

現在我的代碼看起來像這樣和工程就像一個魅力:

public class DoInBackground extends AsyncTask<String, Void, Void> { 

Context mContext; 
LinearLayout mLl; 

String tag = "DynamicFormXML"; 
XmlGuiForm theForm; 
ProgressDialog progressDialog; 
Handler progressHandler; 

public DoInBackground(Context context, LinearLayout ll) { 

    this.mContext = context; 
    this.mLl = ll; 
} 

@Override 
protected void onPreExecute() { 
    super.onPreExecute(); 
} 

@Override 
protected Void doInBackground(String... params) { 

    getFormData(params[0]); 

    return null; 
} 

protected void onPostExecute(Void result) { 
    DisplayForm(); 
} 

我還添加了滾動型和的LinearLayout我activity_main.xml中這樣DisplayForm()看起來像(如果你想跟着我範例前面提到):

private void DisplayForm() { 
    try 
    {   

     // walk thru our form elements and dynamically create them, leveraging our mini library of tools. 
     int i; 
     for (i=0;i<theForm.fields.size();i++) { 
      if (theForm.fields.elementAt(i).getType().equals("text")) { 
       theForm.fields.elementAt(i).obj = new XmlGuiEditBox(mContext,(theForm.fields.elementAt(i).isRequired() ? "*" : "") + theForm.fields.elementAt(i).getLabel(),""); 
       mLl.addView((View) theForm.fields.elementAt(i).obj); 
      } 
    ...