在子片段内的特定间隔后更新TextView

时间:2018-07-10 06:32:11

标签: android android-fragments

我正在尝试制作一个包含一个片段的卡,该片段具有多个textView,这些片段将显示CPU核心的频率。我面临的问题是,我不能在不影响整个Activity性能的情况下更新TextViews。我尝试使用处理程序的postdelayed来调用更新视图所需的函数,但它也冻结了该特定时间间隔的整个UI。 这是我的活动代码和两个片段。

父母片段

package com.psychokernelupdater.frags;

import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.psychokernelupdater.R;

public class TunerMain extends Fragment {

    public TunerMain() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.tuner_main, container, false);
        Fragment cpu = new CPUFreq();
        getChildFragmentManager().beginTransaction()
                .add(R.id.cpuFreqFrag, cpu)
                .commitAllowingStateLoss();

        return view;
    }

}

儿童片段

package com.psychokernelupdater.frags;


import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.text.Html;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.psychokernelupdater.R;

import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.Scanner;

public class CPUFreq extends Fragment {

    static float[] freq = new float[8];
    TextView[] C = new TextView[8];
    float[] fre;
    String[] curFreq = new String[8];
    String units, f;
    String[] cpuData;
    Handler handler = new Handler();
    int delay = 500;

    public CPUFreq() {
    }

    public static float[] getCPUFrequencyCurrent() {
        for (int i = 0; i < 8; i++) {
            try {
                freq[i] = readSystemFileAsInt("/sys/devices/system/cpu/cpu" + String.valueOf(i) + "/cpufreq/scaling_cur_freq");
            } catch (Exception e) {
                freq[i] = -1;
            }
        }
        return freq;
    }

    private static int readSystemFileAsInt(final String pSystemFile) throws Exception {
        InputStream in = null;
        try {
            final Process process = new ProcessBuilder(new String[]{"/system/bin/cat", pSystemFile}).start();

            in = process.getInputStream();
            final String content = readFully(in);
            return Integer.parseInt(content);
        } catch (final Exception e) {
            throw new Exception(e);
        }
    }

    public static final String readFully(final InputStream pInputStream) {
        final StringBuilder sb = new StringBuilder();
        final Scanner sc = new Scanner(pInputStream);
        while (sc.hasNextLine()) {
            sb.append(sc.nextLine());
        }
        return sb.toString();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.cpu_freq, container, false);

        C[0] = (TextView) view.findViewById(R.id.CPU0);
        C[1] = (TextView) view.findViewById(R.id.CPU1);
        C[2] = (TextView) view.findViewById(R.id.CPU2);
        C[3] = (TextView) view.findViewById(R.id.CPU3);
        C[4] = (TextView) view.findViewById(R.id.CPU4);
        C[5] = (TextView) view.findViewById(R.id.CPU5);
        C[6] = (TextView) view.findViewById(R.id.CPU6);
        C[7] = (TextView) view.findViewById(R.id.CPU7);

        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                cpuData = updateFreq();
                updViews(C, cpuData);
                handler.postDelayed(this, delay);
            }
        }, delay);

        return view;
    }

    public String[] updateFreq() {
        fre = getCPUFrequencyCurrent();
        for (int i = 0; i < 8; i++) {
            if (fre[i] == -1) {
                curFreq[i] = " OFFLINE";
            } else {
                if (fre[i] < 1000000) {
                    DecimalFormat df = new DecimalFormat("###");
                    f = df.format(fre[i] / 1000);
                    units = " MHz";
                } else {
                    DecimalFormat df = new DecimalFormat("###.#");
                    f = df.format(fre[i] / 1000000);
                    units = " GHz";
                }
                curFreq[i] = f + units;
            }
        }
        return curFreq;
    }

    public void updViews(TextView[] Arr, String[] cpu) {
        for (int i = 0; i < 8; i++) {
            Arr[i].setText(Html.fromHtml("<b>" + "CPU " + Integer.toString(i + 1) + " : " + "</b>" + cpu[i]));
        }
    }

    @Override
    public void onPause() {
        super.onPause();
    }

}

请告诉我如何在不冻结整个UI的情况下完成此更新。

1 个答案:

答案 0 :(得分:1)

默认情况下,处理程序是在同一线程上创建的。您需要使用处理程序创建一个新线程,如下所示:

HandlerThread thread = new HandlerThread("background");
Handler handler;

现在您可以在onCreateView中启动代码,如下所示:

thread.start();
handler = new Handler(thread.getLooper())
handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        cpuData = updateFreq();
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                updViews(C, cpuData);
            }
        });
        handler.postDelayed(this, delay);
    }
}, delay);

请注意,视图是在runOnUiThread中更新的,否则,您将遇到异常,因为视图只能在UI线程中更新。

也不要忘记在onDestroyView中停止线程:

@Override
public void onDestroyView() {
    super.onDestroyView();
    thread.quitSafely();
}