来自XML的动态android表单

时间:2014-09-29 12:40:17

标签: android xml android-layout android-asynctask android-custom-view

我想在我的activity_main.xml ScrollView中生成一个表单。 XML正确加载和解析,但是当我尝试添加View(LinearLayout)时,它会抛出异常e。我的应用程序通过推送通知获取XML文件的URL,然后解析它。根据XML,它应该生成一个表单并将其显示给用户。我以此为例:https://www.ibm.com/developerworks/xml/tutorials/x-andddyntut/#l1

这是我的主要活动:

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

我认为主要活动的上下文以及主要活动中的空Scrollview都是正确转发的(它们不是空的)但我不是100%肯定。任何帮助/提示表示赞赏! :)

2 个答案:

答案 0 :(得分:1)

您无法从后台线程(例如运行doInBackground方法的线程)触摸GUI。

AsynTask中,您可以将UI代码放在onPostExecute中,在UI线程上调用,结果为doInBackground

如果您有中间结果,可以从doInBackground调用publishProgress,这将触发在UI线程上调用onProgressUpdate,您可以在其中更新UI。

有关示例以及有关在哪个线程上必须执行的操作的更多详细信息,请参阅AsyncTask API

答案 1 :(得分: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();
}

我还将ScrollView和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);
            }
    ...