Java Android“只有创建视图层次结构的原始线程才能触及其视图。” 片段错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18656813/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 09:54:55  来源:igfitidea点击:

Android "Only the original thread that created a view hierarchy can touch its views." error in Fragment

javaandroidmultithreadingandroid-fragments

提问by David

I've got this simple timer in my app which is runs in every 3 seconds. It works perfectly if it's not in a fragment class. But here in fragment I always got the error: Only the original thread that created a view hierarchy can touch its views.

我的应用程序中有这个简单的计时器,每 3 秒运行一次。如果它不在片段类中,它就可以完美运行。但是在片段中,我总是遇到错误:只有创建视图层次结构的原始线程才能触及其视图。

timer = new Timer();

timer.schedule(new TimerTask() {

    @Override
    public void run() {
        String timeStamp = new SimpleDateFormat(
                "yyyy.MM.dd HH:mm:ss").format(Calendar
                .getInstance().getTime());
        System.out.println("TimeStamp: " + timeStamp);
        // Read And Write Register Sample
        port = Integer.parseInt(gConstants.port);
        String refe = "0";// HEX Address
        ref = Integer.parseInt(refe, 16);// Hex to int
        count = 10; // the number Address to read
        SlaveAddr = 1;
        astr = gConstants.ip; // Modbus Device

        InetAddress addr;
        try {
            addr = InetAddress.getByName(astr);
            con = new TCPMasterConnection(addr); // the
            // connection
        } catch (UnknownHostException e2) {
            e2.printStackTrace();
        }

        // 1.Prepare the request
        /************************************/
        Rreq = new ReadMultipleRegistersRequest(ref, count);
        Rres = new ReadMultipleRegistersResponse();

        Rreq.setUnitID(SlaveAddr); // set Slave Address
        Rres.setUnitID(SlaveAddr); // set Slave Address

        // 2. Open the connection
        con.setPort(port);
        try {
            con.connect();
            System.out.println("Kapcsolódva!");
        } catch (Exception e1) {
            e1.printStackTrace();
        }
        con.setTimeout(2500);
        // 3. Start Transaction
        trans = new ModbusTCPTransaction(con);
        trans.setRetries(5);
        trans.setReconnecting(true);
        trans.setRequest(Rreq);

        try {
            trans.execute();
        } catch (ModbusIOException e) {
            e.printStackTrace();
        } catch (ModbusSlaveException e) {
            e.printStackTrace();
        } catch (ModbusException e) {
            e.printStackTrace();
        }
        /* Print Response */
        Rres = (ReadMultipleRegistersResponse) trans
                .getResponse();

        System.out.println("Connected to=  " + astr
                + con.isConnected() + " / Start Register "
                + Integer.toHexString(ref));

        count = 10;
        for (int k = 0; k < count; k++) {
            System.out.println("The value READ: "
                    + Rres.getRegisterValue(k) + " "
                    + Rres.getUnitID());
            ki_adat = ki_adat + Rres.getRegisterValue(k) + "\n";


            // Adatbázisba írás
            ContentValues modbusData = new ContentValues();
            modbusData.put("Value", Rres.getRegisterValue(k)); // tábla
                                                                // +
                                                                // érték
            modbusData.put("timeStamp", timeStamp);
            try {
                gConstants.db.beginTransaction();
                gConstants.db
                        .insert("Modbus", null, modbusData);
                gConstants.db.setTransactionSuccessful();
            } finally {
                gConstants.db.endTransaction();
            }

        }
        kiir.setText(ki_adat);
        ki_adat = "";
    }//run vége

}, 0, 3000);

采纳答案by matthewrdev

This error occurs when trying to access UI elements from any thread that is not the UI thread.

尝试从非 UI 线程的任何线程访问 UI 元素时会发生此错误。

To access/modify elements from a non-UI-thread, use runOnUIThread.

要从非 UI 线程访问/修改元素,请使用runOnUIThread.

However as you need to change a UI element from within a fragment, runOnUIThreadshould be invoked onto the fragments owning activity. You can do this through getActivity().runOnUIThread().

但是,当您需要从 中更改 UI 元素时fragmentrunOnUIThread应在拥有活动的片段上调用 ​​, 。您可以通过getActivity().runOnUIThread().

EG:

例如:

timer.schedule(new TimerTask() {
    @Override
    public void run() {
        // Your logic here...

        // When you need to modify a UI element, do so on the UI thread. 
        // 'getActivity()' is required as this is being ran from a Fragment.
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                // This code will always run on the UI thread, therefore is safe to modify UI elements.
                myTextBox.setText("my text");
            }
        });
    }
}, 0, 3000); // End of your timer code.

For further information see the following documentation:

有关更多信息,请参阅以下文档:

  1. Android Fragments(specifically, getActivity()).
  2. TimerTask.
  3. Invoking a Runnable on the UI thread.
  1. Android 片段(特别是getActivity())。
  2. 定时器任务
  3. 在 UI 线程上调用 Runnable。

回答by Cob50nm

you need to use the runOnUIThread()function I have an example somwhere that I will post when I find it.

你需要使用runOnUIThread()我有一个例子的功能,当我找到它时我会发布它。

you need to give your timer an instance of MainActivity alternatively see this question I asked Android image timing issueswith what sounds like a similar thing to what you were trying to do

你需要给你的计时器一个 MainActivity 的实例,或者看到这个问题我问了Android 图像计时问题,听起来与你试图做的事情相似

public static void updateText(Activity act, resID)
{

 loadingText = (TextView) activity.findViewById(R.id.loadingScreenTextView);
          act.runOnUiThread(new Runnable() 
                {
                     public void run() 
                     {
                       loadingText.setText(resID);

                     }

                });
}

回答by Ritesh Gune

You are doing UI operation from another thread. I suggest you to use following.

您正在从另一个线程进行 UI 操作。我建议你使用以下。

runOnUiThread(new Runnable() {  
                @Override
                public void run() {

                    kiir.setText(ki_adat);
                }                   

回答by Girish Nair

Try this

尝试这个

new CountDownTimer(365*24*60*60, 3000) {

 public void onTick(long millisUntilFinished) {
     String timeStamp = new SimpleDateFormat(
                        "yyyy.MM.dd HH:mm:ss").format(Calendar
                        .getInstance().getTime());
                System.out.println("TimeStamp: " + timeStamp);
                // Read And Write Register Sample
                port = Integer.parseInt(gConstants.port);
                String refe = "0";// HEX Address
                ref = Integer.parseInt(refe, 16);// Hex to int
                count = 10; // the number Address to read
                SlaveAddr = 1;
                astr = gConstants.ip; // Modbus Device

                InetAddress addr;
                try {
                    addr = InetAddress.getByName(astr);
                    con = new TCPMasterConnection(addr); // the
                    // connection
                } catch (UnknownHostException e2) {
                    // TODO Auto-generated catch block
                    e2.printStackTrace();
                }

                // 1.Prepare the request
                /************************************/
                Rreq = new ReadMultipleRegistersRequest(ref, count);
                Rres = new ReadMultipleRegistersResponse();

                Rreq.setUnitID(SlaveAddr); // set Slave Address
                Rres.setUnitID(SlaveAddr); // set Slave Address

                // 2. Open the connection
                con.setPort(port);
                try {
                    con.connect();
                    System.out.println("Kapcsolódva!");
                } catch (Exception e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                con.setTimeout(2500);
                // 3. Start Transaction
                trans = new ModbusTCPTransaction(con);
                trans.setRetries(5);
                trans.setReconnecting(true);
                trans.setRequest(Rreq);

                try {
                    trans.execute();
                } catch (ModbusIOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ModbusSlaveException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ModbusException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                /* Print Response */
                Rres = (ReadMultipleRegistersResponse) trans
                        .getResponse();

                System.out.println("Connected to=  " + astr
                        + con.isConnected() + " / Start Register "
                        + Integer.toHexString(ref));

                count = 10;
                for (int k = 0; k < count; k++) {
                    System.out.println("The value READ: "
                            + Rres.getRegisterValue(k) + " "
                            + Rres.getUnitID());
                    ki_adat = ki_adat + Rres.getRegisterValue(k) + "\n";


                    // Adatbázisba írás
                    ContentValues modbusData = new ContentValues();
                    modbusData.put("Value", Rres.getRegisterValue(k)); // tábla
                                                                        // +
                                                                        // érték
                    modbusData.put("timeStamp", timeStamp);
                    try {
                        gConstants.db.beginTransaction();
                        gConstants.db
                                .insert("Modbus", null, modbusData);
                        gConstants.db.setTransactionSuccessful();
                    } finally {
                        gConstants.db.endTransaction();
                    }

                }
                kiir.setText(ki_adat);
                ki_adat = "";
 }

 public void onFinish() {}
}.start();

回答by flawyte

2 solutions :

2个解决方案:

And put the myTextView.setText(str)call in the run()method of the Runnableobject.

并将myTextView.setText(str)调用放在对象的run()方法中Runnable

回答by Jevgenij Kononov

TRY THIS: put this part of code somewhere but not in activity onCreate method

试试这个:把这部分代码放在某个地方,但不要放在 onCreate 方法的活动中

public void LoadTable(final String u, final String k) {

公共无效负载表(最终字符串 u,最终字符串 k){

    //  runOnUiThread need to be used or error will appear 
    new AsyncTask<Void, Void, Void>() {
        @Override
        protected Void doInBackground(Void... params) {
            try {

                runOnUiThread(new Runnable() {

                    @Override
                    public void run() {
                       //method which was problematic and was casing a problem
                       createTable(u, k);
                    }
                });
            } catch (Exception exception) {
                createAndShowDialog(exception, "Error");
            }
            return null;
        }
    }.execute();
}

回答by frapeti

Try this:

尝试这个:

textView.post(new Runnable() {
    @Override
    public void run() {
    textView.setText("Hello!"); }
});