【问题标题】:add view (text view) in AsyncTask在 AsyncTask 中添加视图(文本视图)
【发布时间】:2013-07-26 07:25:11
【问题描述】:

我使用下面的代码在异步任务中添加文本视图,但是:

07-26 11:40:39.302: E/AndroidRuntime(26715): Uncaught handler: thread AsyncTask #1 exiting due to uncaught exception
07-26 11:40:39.312: E/AndroidRuntime(26715): java.lang.RuntimeException: An error occured while executing doInBackground()
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.os.AsyncTask$3.done(AsyncTask.java:200)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.FutureTask.run(FutureTask.java:137)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1068)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:561)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.lang.Thread.run(Thread.java:1096)
07-26 11:40:39.312: E/AndroidRuntime(26715): Caused by: android.view.ViewRoot$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.ViewRoot.checkThread(ViewRoot.java:2683)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.ViewRoot.invalidateChild(ViewRoot.java:570)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.ViewRoot.invalidateChildInParent(ViewRoot.java:596)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.ViewGroup.invalidateChild(ViewGroup.java:2481)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.View.invalidate(View.java:5027)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.ViewGroup.addView(ViewGroup.java:1840)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.view.ViewGroup.addView(ViewGroup.java:1821)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at com.learning.chiazi.MainActivity.addTextView(MainActivity.java:180)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at com.learning.chiazi.MainActivity$Proccess.doInBackground(MainActivity.java:243)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at com.learning.chiazi.MainActivity$Proccess.doInBackground(MainActivity.java:1)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at android.os.AsyncTask$2.call(AsyncTask.java:185)
07-26 11:40:39.312: E/AndroidRuntime(26715):    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
07-26 11:40:39.312: E/AndroidRuntime(26715):    ... 4 more
07-26 11:40:39.342: E/SemcCheckin(26715): Get crash dump level : java.io.FileNotFoundException: /data/semc-checkin/crashdump

我该如何解决这个问题?

代码:

   public void addTextView(int belowId, int id,String text){
        RelativeLayout rSub= (RelativeLayout) findViewById(R.id.rSub);
        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
                RelativeLayout.LayoutParams.WRAP_CONTENT,
                RelativeLayout.LayoutParams.WRAP_CONTENT);
        lp.addRule(RelativeLayout.BELOW, belowId);
        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);

        TextView tv = new TextView(this);
        tv.setId(id);

        tv.setText(text+"\n");
        rSub.addView(tv, lp);

    }

   class Proccess extends AsyncTask<Void, Void, Void>{

        @Override
        protected Void doInBackground(Void... arg0) {
            addTextView(R.id.tvResult, 1234, "s");
            return null;
        }
    }

【问题讨论】:

  • 你为什么要异步任务只是为了做到这一点addTextView(R.id.tvResult, 1234, "s");

标签: java android view android-asynctask


【解决方案1】:

使用此代码,它对我有用:

public class MainActivity extends Activity {

    Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            // TODO Auto-generated method stub
            super.handleMessage(msg);
            TextView tvMain = (TextView) findViewById(R.id.tvMain);

                tvMain.setText(msg.getData().get("KEY")+"Button Proceed");
            }
        };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        /*Button btnDemo = (Button) findViewById(R.id.btnDemo);
        btnDemo.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub

                myAsyncTak();
            }


        });*/

        new AddTask().execute();
    }

    private void myAsyncTak() {
        // TODO Auto-generated method stub
        Runnable runnable = new Runnable() {

            @Override
            public void run() {
                // TODO Auto-generated method stub

                TextView textView=new TextView(MainActivity.this);
                textView.setLayoutParams(new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, 50));
                textView.setText("Newly Added TextView");
                View v=View.inflate(MainActivity.this, R.layout.activity_main, null);
                ((RelativeLayout)v).addView(textView);
                setContentView(v);

                Message msg=new Message();
                Bundle bundle=new Bundle();
                bundle.putString("KEY", "Saurabh");
                msg.setData(bundle);
                handler.sendMessage(msg);
                //handler.sendEmptyMessage(0);
            }
        };

        Thread myThread=new Thread(runnable);
        myThread.start();
    }
    public class AddTask extends AsyncTask<String, Integer, String>{

        @Override
        protected void onPreExecute() {
            // TODO Auto-generated method stub
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... params) {
            // TODO Auto-generated method stub
            myAsyncTak();
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
        }
    }


}

还有这个布局:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" 
    android:id="@+id/rlMain" >

    <TextView android:id="@+id/tvMain"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="@string/hello_world" />

    <Button
        android:id="@+id/btnDemo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/tvMain"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="42dp"
        android:text="Demo" />

</RelativeLayout>

【讨论】:

  • @Erfan13 此代码适用于在异步任务中添加文本视图或任何视图。您可以实现此代码。
【解决方案2】:

像这样在后台运行 UI 线程

@Override
        protected Void doInBackground(Void... arg0) {
            this.runOnUiThread(new Runnable() {
            public void run() {
                addTextView(R.id.tvResult, 1234, "s");
        });
            return null;
        }

【讨论】:

  • 我应该导入什么?
  • 无需导入任何东西
【解决方案3】:

UI 作品应位于主线程中。

在 android AsyncTask.doInBackground() 中,顾名思义,仅适用于网络、数据库访问等后台作业。

您的方法addTextView() 应该位于AsyncTask.onPostExecute()

【讨论】:

    【解决方案4】:

    您无法更改doInBackground() 中的 GUI 试试这个,这样您就可以在 UI 线程上进行更改,同时仍然保留 doInBackground() 中的代码:

    @Override
        protected Void doInBackground(Void... arg0) {
           Runnable run = new Runnable() 
           {
                public void run() 
                {
                    addTextView(R.id.tvResult, 1234, "s");
                }
        }; return null;
    }
    

    但请注意,涉及 GUI 更改的操作最好位于 onPostExecute()onCreate() 中。无论如何,这是最佳做法:)

    可能需要时间才能完成的操作,例如运行长时间的数据库查询或其他可能强制关闭应用程序的情况,应位于doInBackground()

    【讨论】:

    • 对于onPostExecute(),只需右键单击 Activity 类的域 ( { .... } ) 中的任意位置,转到 Source > Override / Implement Methods,勾选 onPostExecute() 并点击 OK。 (如果您使用的是 Eclipse)
    • 完成后,将 TextView 中更改的代码放在新方法中。
    • 抱歉,在 AsyncTask 类域内的任意位置右击.....我肯定还在睡觉:|
    【解决方案5】:

    不能在AsyncTaskdoInBackground()方法中添加TextView,因为该方法在backgronud线程中操作,不能在UI Thread中进行操作,尝试将TextView添加到onPreExecute()/onPostExecute() 或出doInBackground()

    【讨论】:

    • 但我想在后台添加它!
    • 为什么要在后台进行 UI 操作?
    • @Erfan13 也只是添加了一个视图,为什么你甚至需要一个异步任务
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多