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); 
      } 
    ...