【问题标题】:Android StrictMode: False positive or what is wrong with this sample?Android StrictMode:误报或此示例有什么问题?
【发布时间】:2012-07-21 15:50:50
【问题描述】:

我有这个切换按钮,当某个条件(网站内容)为真时启用。

getSystemOnState(..) 连接到网络服务器,由于严格模式,这会导致异常。我使用 Handler 类的方式有什么问题?

public class ReceiverToggleButton extends ToggleButton {
 private Runnable mTicker;
 private Handler mHandler;
 private boolean mTickerStopped = false;
 private String rxhost = null;
 private Context context = null;

 public ReceiverToggleButton(Context context) {
    super(context);
    this.context = context;
    updateOnOffState(context);
 }

 private void updateOnOffState(final Context cxt) {
    Runnable r = new Runnable() {
        public void run() {
            rxhost = cxt.getResources().getString(R.string.host_receiver);
            mHandler = new Handler();
            mTicker = new Runnable() {
                public void run() {
                    if (mTickerStopped) {
                        return;
                    }

                    boolean isSystemOn = getSystemOnState(rxhost); // connects to webserver
                    setChecked(isSystemOn);
                    invalidate();
                    long now = SystemClock.uptimeMillis();
                    long next = now + 1000 * 10; // check every 10s
                    mHandler.postAtTime(this, next);
                }

            };
            mHandler.post(mTicker);
        }
    };
    new Thread(r).start();
 }
}

【问题讨论】:

    标签: android android-strictmode strict-mode


    【解决方案1】:

    严格模式正在抱怨,因为您仍在尝试在 UI 线程上执行该网络操作。或者这个类被广播接收器(它们是短暂的)调用。 处理程序也可以传递消息,在这个例子中你并没有真正正确地使用它们。或者至少您可以看到所有线程、可运行文件和发布如何使所有内容难以阅读。

    你需要的是 AsyncTask。

    这是来自 http://developer.android.com/reference/android/os/AsyncTask.html 的 Google 示例

    private class DownloadFilesTask extends AsyncTask<URL, Integer, Long> {
         protected Long doInBackground(URL... urls) {
             int count = urls.length;
             long totalSize = 0;
             for (int i = 0; i < count; i++) {
                 totalSize += Downloader.downloadFile(urls[i]);
                 publishProgress((int) ((i / (float) count) * 100));
                 // Escape early if cancel() is called
                 if (isCancelled()) break;
             }
             return totalSize;
         }
    
         protected void onProgressUpdate(Integer... progress) {
             setProgressPercent(progress[0]);
         }
    
         protected void onPostExecute(Long result) {
             showDialog("Downloaded " + result + " bytes");
         }
     }
    
    new DownloadFilesTask().execute(url1, url2, url3);
    

    在您的情况下,您希望第一个参数是您的主机字符串,您在后台执行的操作将执行您的检查和您的网络调用,并且 onPostExecute(在 UI 线程上运行)来更新您的视图。

    【讨论】:

    • 谢谢!现在我只是想知道如何正确使用处理程序 - 我使用了这个tutorial,我看不出我在做什么不同。
    • 是的。我想这种方式可行,但它不是很干净。根据我的经验,当您有 2 个需要相互交谈的类(通常在不同的线程上)时,处理程序会很好。例如,MusicService 试图将更新发送回 Activity。 (相反的方式可以只使用 IntentService)所以我想我只在打开并执行一些操作的小消息(通常是 id)的单向通信方面取得了巨大成功。
    • 这与我的用例(不是发布的,而是相同的应用程序)略有不同。我有一个 textview 显示在远程系统上播放的当前歌曲(通过 HTTP 查询的 XBMC)。所以每隔 N 秒我想查询 XBMC 并显示歌曲的名称。我目前的方法是 AsyncTasks,使用 java.util.TimerTasks 安排 - 我会看看它是否有效。
    • 啊,我明白了。就像我提到的 AsyncTasks 很有用,因为您可以在后台线程上执行查询。然后将该字符串传递给您的 onPostExecute,然后更新您的 UI。所以你的参数应该看起来像 AsyncTask 基本上映射到
    • 我只是尝试使用计时器任务 - 它不起作用:我尝试运行 Looper.prepare() 一次(以便能够对 UI 进行更改),但随后任务中止(甚至没有一个堆栈跟踪)在回调 onPostExecute() 时。我想我必须使用线程、任务等来实现这一点很好,但对于重复使用并没有真正的帮助。
    猜你喜欢
    • 1970-01-01
    • 2016-08-03
    • 2011-02-22
    • 2010-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-29
    相关资源
    最近更新 更多