0

I have a bunch of UI being updated by a loop that is constantly being called. However it seems to get bogged down; how would I go about using a AsyncTask to make it a bit quicker?

Here is the loop for the UI:

class Looper extends BaseIOIOLooper {

    /**
     * Called every time a connection with IOIO has been established.
     * Typically used to open pins.
     * 
     * @throws ConnectionLostException
     *             When IOIO connection is lost.
     * 
     * @see ioio.lib.util.AbstractIOIOActivity.IOIOThread#setup()
     */
    @Override
    protected void setup() throws ConnectionLostException {
        led_ = ioio_.openDigitalOutput(0, true);

        DO1 = ioio_.openDigitalOutput(6, false);
        DO2 = ioio_.openDigitalOutput(7, false);
        DO3 = ioio_.openDigitalOutput(8, false);
        DO4 = ioio_.openDigitalOutput(9, false);
        DO5 = ioio_.openDigitalOutput(10, false);
        DO6 = ioio_.openDigitalOutput(11, false);
        DO7 = ioio_.openDigitalOutput(12, false);
        DO8 = ioio_.openDigitalOutput(13, false);
        DO9 = ioio_.openDigitalOutput(14, false);
        DO10 = ioio_.openDigitalOutput(15, false);
        DO11 = ioio_.openDigitalOutput(16, false);
        DO12 = ioio_.openDigitalOutput(17, false);

        DI1 = ioio_.openDigitalInput(18);
        DI2 = ioio_.openDigitalInput(19);
        DI3 = ioio_.openDigitalInput(20);
        DI4 = ioio_.openDigitalInput(21);
        DI5 = ioio_.openDigitalInput(22);
        DI6 = ioio_.openDigitalInput(23);
        DI7 = ioio_.openDigitalInput(24);
        DI8 = ioio_.openDigitalInput(25);
        DI9 = ioio_.openDigitalInput(26);

        AI1 = ioio_.openAnalogInput(31);
        AI2 = ioio_.openAnalogInput(32);
        AI3 = ioio_.openAnalogInput(33);
        AI4 = ioio_.openAnalogInput(34);
        AI5 = ioio_.openAnalogInput(35);
        AI6 = ioio_.openAnalogInput(36);
        AI7 = ioio_.openAnalogInput(37);
        AI8 = ioio_.openAnalogInput(38);
        AI9 = ioio_.openAnalogInput(39);
        AI10 = ioio_.openAnalogInput(40);
        AI11 = ioio_.openAnalogInput(41);
        AI12 = ioio_.openAnalogInput(42);
        AI13 = ioio_.openAnalogInput(43);
        AI14 = ioio_.openAnalogInput(44);
        AI15 = ioio_.openAnalogInput(45);
        AI16 = ioio_.openAnalogInput(46);
        /*
         * for (int i = 0; i < DOA.length; i++) { DOA[i] =
         * ioio_.openDigitalOutput(i + 6); }
         */

        // for (int i = 0; i < DIA.length; i++) {
        // DIA[i] = ioio_.openDigitalInput(i + 18);
        // }
        // for (int i = 0; i < PWMA.length; i++) {
        // PWMA[i] = ioio_.openPwmOutput(i + 27, 10000);
        // }
        //
        // for (int i = 0; i < AIA.length; i++) {
        // AIA[i] = ioio_.openAnalogInput(i + 31);
        // }
        // TWIA[0] = ioio_.openTwiMaster(1, TwiMaster.Rate.RATE_1MHz,
        // false);
        // TWIA[1] = ioio_.openTwiMaster(2, TwiMaster.Rate.RATE_1MHz,
        // false);
        // TWIA[2] = ioio_.openTwiMaster(4, TwiMaster.Rate.RATE_1MHz,
        // false);
        // TWIA[3] = ioio_.openTwiMaster(5, TwiMaster.Rate.RATE_1MHz,
        // false);
        connStatus = true;
    }

    /**
     * Called repetitively while the IOIO is connected.
     * 
     * @throws ConnectionLostException
     *             When IOIO connection is lost.
     * @throws InterruptedException
     * 
     * @see ioio.lib.util.AbstractIOIOActivity.IOIOThread#loop()
     */
    @Override
    public void loop() throws ConnectionLostException, InterruptedException {
        led_.write(false);

        DO1.write(currentDigFrag.digitalIO0Power.isChecked());
        DO2.write(currentDigFrag.digitalIO1Power.isChecked());
        DO3.write(currentDigFrag.digitalIO2Power.isChecked());
        DO4.write(currentDigFrag.digitalIO3Power.isChecked());
        DO5.write(currentDigFrag.digitalIO4Power.isChecked());
        DO6.write(currentDigFrag.digitalIO5Power.isChecked());
        DO7.write(currentDigFrag.digitalIO6Power.isChecked());
        DO8.write(currentDigFrag.digitalIO7Power.isChecked());
        DO9.write(currentDigFrag.digitalIO8Power.isChecked());
        DO10.write(currentDigFrag.digitalIO9Power.isChecked());
        DO11.write(currentDigFrag.digitalIO10Power.isChecked());
        DO12.write(currentDigFrag.digitalIO11Power.isChecked());

        UITask
        currentDigFrag.updateDigitalInput(1, !DI1.read());
        currentDigFrag.updateDigitalInput(2, !DI2.read());
        currentDigFrag.updateDigitalInput(3, !DI3.read());
        currentDigFrag.updateDigitalInput(4, !DI4.read());
        currentDigFrag.updateDigitalInput(5, !DI5.read());
        currentDigFrag.updateDigitalInput(6, !DI6.read());
        currentDigFrag.updateDigitalInput(7, !DI7.read());
        currentDigFrag.updateDigitalInput(8, !DI8.read());
        currentDigFrag.updateDigitalInput(9, !DI8.read());

        currentAnFrag.updateAnalogInput(1,AI1.getVoltage());
        currentAnFrag.updateAnalogInput(2,AI2.getVoltage());
        currentAnFrag.updateAnalogInput(3,AI3.getVoltage());
        currentAnFrag.updateAnalogInput(4,AI4.getVoltage());
        currentAnFrag.updateAnalogInput(5,AI5.getVoltage());
        currentAnFrag.updateAnalogInput(6,AI6.getVoltage());
        currentAnFrag.updateAnalogInput(7,AI7.getVoltage());
        currentAnFrag.updateAnalogInput(8,AI8.getVoltage());
        currentAnFrag.updateAnalogInput(9,AI9.getVoltage());
        currentAnFrag.updateAnalogInput(10,AI10.getVoltage());
        currentAnFrag.updateAnalogInput(11,AI11.getVoltage());
        currentAnFrag.updateAnalogInput(12,AI12.getVoltage());
        currentAnFrag.updateAnalogInput(13,AI13.getVoltage());
        currentAnFrag.updateAnalogInput(14,AI14.getVoltage());
        currentAnFrag.updateAnalogInput(15,AI15.getVoltage());
        currentAnFrag.updateAnalogInput(16,AI16.getVoltage());
    }
}

And here is what I've implemented with AsyncTask so far; I'm a bit confused:

     private class UIAsyncTask extends AsyncTask<analogFragment, Float, Void> {

        @Override
protected Void doInBackground(analogFragment... params) {
            //What do I do in here???
            return null;
        }

     }

Note: both classes are inner classes.

Also note: The currentDigFrag and currentAnFrag are just current Fragments that contain the views; particular the ProgressBar views

Here's what I've tried, without results:

private class AnalogUpdater extends AsyncTask<AnalogInput, Void, Void> {

    // A callback method executed on non UI thread, invoked after
    // onPreExecute method if exists

    // Takes a set of parameters of the type defined in your class
    // implementation. This method will be
    // executed on the background thread, so it must not attempt to interact
    // with UI objects.
    @Override
    protected Void doInBackground(AnalogInput... params) {
        try {
            currentAnFrag.updateAnalogInput(1, AI1.getVoltage());
            currentAnFrag.updateAnalogInput(2, AI2.getVoltage());
            currentAnFrag.updateAnalogInput(3, AI3.getVoltage());
            currentAnFrag.updateAnalogInput(4, AI4.getVoltage());
            currentAnFrag.updateAnalogInput(5, AI5.getVoltage());
            currentAnFrag.updateAnalogInput(6, AI6.getVoltage());
            currentAnFrag.updateAnalogInput(7, AI7.getVoltage());
            currentAnFrag.updateAnalogInput(8, AI8.getVoltage());
            currentAnFrag.updateAnalogInput(9, AI9.getVoltage());
            currentAnFrag.updateAnalogInput(10, AI10.getVoltage());
            currentAnFrag.updateAnalogInput(11, AI11.getVoltage());
            currentAnFrag.updateAnalogInput(12, AI12.getVoltage());
            currentAnFrag.updateAnalogInput(13, AI13.getVoltage());
            currentAnFrag.updateAnalogInput(14, AI14.getVoltage());
            currentAnFrag.updateAnalogInput(15, AI15.getVoltage());
            currentAnFrag.updateAnalogInput(16, AI16.getVoltage());
        } catch (ConnectionLostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

    // A callback method executed on UI thread, invoked by the
    // publishProgress()
    // from doInBackground() method

    // Overrider this handler to post interim updates to the UI thread. This
    // handler receives the set of parameters
    // passed in publishProgress from within doInbackground.
}

}

Timothy Frisch
  • 2,995
  • 2
  • 30
  • 64
  • Let's understand the problem better first, before we try to choose "how" to handle it. What is the trigger that causes the setup method to be called (repetitively, right?). What changes between setup calls? Are all of the UI elements visible, or are just some of them visible at any one time? Describe the context within which the set of code you have shown is called. – ErstwhileIII Mar 06 '14 at 18:04
  • Only the Loop() is called repeatedly. – Timothy Frisch Mar 06 '14 at 18:05
  • All UI Elements from the currentDigFrag and currentAnFrag are always visible (The application is a multi-tabbed activity with fragments controlling the UI) – Timothy Frisch Mar 06 '14 at 18:05
  • When the Loop() calls; it updates the UI with the .updateDigitalInput() and .updateAnalogInput() methods I have written in their respective fragments. – Timothy Frisch Mar 06 '14 at 18:06
  • And what conditions change outside the loop (some or all); What UI elements are visible (all of them)? Are you, essentially, monitoring changes that can occur in real-time across each element for which you need to change UI? There may be some optimization that can be done within the loop itself and then you may want to run it in the background) – ErstwhileIII Mar 06 '14 at 18:08
  • The Loop is ran during an IOIO-OTG connection (a device that connects to the USB); and all the UI views are visible and change upon user interaction with the IOIO-OTG board whilst it is connected. So for instance if I put a 3.3 volt electric current into analogInput0's corresponding pin, it does adjust the progressBar corresponding to that analogInput with a voltage level. However it is slow due to the unoptimized nature of the Loop();. – Timothy Frisch Mar 06 '14 at 18:10

1 Answers1

1

So here you have to be aware of what functions AsyncTask have access to the UI thread. The most common used being onProgressUpdate.

In order to call this function, call publishProgress(Float... progress) (give it either a single Float or an array of Floats) and in your onProgressUpdate() function you update all of the UI you need to using the array of Floats.

In doInBackground, you would simply put your looping logic in here, store what variables you need, and at the end of every loop, or every other loop, or even after pausing the loop for a set amount of time, you would call publishProgress in the method I stated earlier.

Other methods you may want to override are onPreExecute() and onPostExecute() just in case you want to have any extra setup before and after doInBackground() executes.

http://www.vogella.com/tutorials/AndroidBackgroundProcessing/article.html#concurrency_asynchtask is a good read

Salvite
  • 137
  • 1
  • 9
  • Would I put the Async Task within my Loop()? Sorry I am just a bit new to Android and it is a little confusing. – Timothy Frisch Mar 06 '14 at 18:17
  • No, you would create a while or for loop inside of doInBackground() and then place everything in loop() inside of the while/for loop. – Salvite Mar 06 '14 at 18:41
  • The problem with that is the loop is specific to the connection of the IOIO-OTG and it wouldn't ever start? – Timothy Frisch Mar 06 '14 at 18:53