31

アプリには、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);
4

7 に答える 7

99

このエラーは、UI スレッドではないスレッドから UI 要素にアクセスしようとすると発生します。

非 UI スレッドから要素にアクセス/変更するには、 を使用しますrunOnUIThread

ただし、UI 要素を 内から変更する必要があるためfragmentrunOnUIThreadフラグメントを所有するアクティビティに対して を呼び出す必要があります。を通じてこれを行うことができますgetActivity().runOnUIThread()

例えば:

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.

詳細については、次のドキュメントを参照してください。

  1. Android フラグメント(具体的にはgetActivity())。
  2. タイマータスク.
  3. UI スレッドで Runnable を呼び出す。
于 2013-09-06T11:38:30.240 に答える
8

関数を使用する必要がありますrunOnUIThread()。私が見つけたときに投稿する例があります。

タイマーに 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);

                     }

                });
}
于 2013-09-06T11:34:37.980 に答える
3

別のスレッドから UI 操作を行っています。以下を使用することをお勧めします。

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

                    kiir.setText(ki_adat);
                }                   
于 2013-09-06T11:38:12.757 に答える
1

これを試して:

textView.post(new Runnable() {
    @Override
    public void run() {
    textView.setText("Hello!"); }
});
于 2017-03-25T22:41:13.933 に答える
0

これを試してください: コードのこの部分をどこかに置きますが、アクティビティではありません onCreate メソッド

public void LoadTable(最終文字列 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();
}
于 2016-10-14T15:45:50.470 に答える