You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AngularJS+Cordova APP数据无法自动刷新,点击屏幕才刷新问题求助

解决AngularJS + Cordova应用中SQLite数据加载后视图不自动刷新的问题

你遇到的核心问题是SQLite异步回调的执行上下文不在Angular的变更检测循环内,而且你的$scope.safeApply()调用时机不对——它在异步回调完成前就执行了,导致Angular完全不知道后续数据的变化。

问题拆解

你的代码里,db.transaction和executeSql都是异步操作:当你在db.transaction函数里直接调用$scope.safeApply()时,executeSql的成功回调还没开始执行,$scope.datas还是空数组。等真正从数据库拿到数据并push到数组时,Angular的变更检测已经结束了,所以视图不会自动更新;只有当你点击屏幕触发了digest循环(比如通过Angular内置的事件指令),视图才会同步最新数据。

修复方案

把触发变更检测的代码($scope.$apply()或$scope.safeApply())放到executeSql的成功回调内部——也就是数据真正被添加到$scope.datas之后。同时可以简化代码,不用把每个字段都单独赋值到$scope上:

$scope.datas = []; 
db.transaction(function(transaction) { 
  transaction.executeSql('SELECT * FROM application_data', [], function (tx, results) { 
    var len = results.rows.length;
    for (var i = 0; i < len; i++){
      // 直接从结果中取出数据push,无需额外赋值到$scope属性
      var item = results.rows.item(i);
      $scope.datas.push({
        id: item.id, 
        name: item.name, 
        date: item.date
      });
    }
    // 数据更新完成后,手动触发Angular变更检测
    if (!$scope.$$phase) { // 先检查是否已在digest循环中,避免重复触发报错
      $scope.$apply();
    }
    // 如果用自定义的safeApply,确保它内部有类似的检测逻辑,直接调用即可
    // $scope.safeApply();
  }, null); 
}); 

额外补充

  • 如果你使用的safeApply是自定义函数,它的实现应该包含对$$phase的检测,避免在已经处于digest循环时调用$apply()导致错误。典型的safeApply实现如下:
    $scope.safeApply = function(fn) {
      var phase = this.$root.$$phase;
      if(phase === '$apply' || phase === '$digest') {
        if(fn && (typeof(fn) === 'function')) {
          fn();
        }
      } else {
        this.$apply(fn);
      }
    };
    
  • 也可以用$timeout替代$apply,因为$timeout会自动触发Angular的变更检测,而且不需要手动检查$$phase:
    // 在for循环结束后替换成:
    $timeout(function() {
      // 无需额外操作,$timeout会自动触发digest循环
    });
    

这样修改后,当数据库查询完成并更新$scope.datas后,Angular会立即检测到变化并刷新视图,不再需要手动点击屏幕触发。

内容的提问来源于stack exchange,提问作者user3740961

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:45:29