安卓Cordova的离线预填数据库SQLitePlugin [帮助请求] [英] Ionic Prepopulated Database with Antair Cordova SQLitePlugin [help request]

查看:521
本文介绍了安卓Cordova的离线预填数据库SQLitePlugin [帮助请求]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

____ INTRO



大家好,首先,三个澄清:


$ b


  1. 我的英语不好,所以我请你原谅我的错误。

  2. 我以前搜索过并尝试过在互联网上找到的解决方案,但仍然可以未解决嵌入预填充数据库的问题。

    >

    我想使用预先填充的数据库开发适用于iOS和Android的应用程序。



    例如,数据库由 15.000个记录组成,每个由三个键值对( id firstname lastname <



    步骤:

    >

      ionic start myapp blank 
    cd myapp
    离子平台添加ios
    离子平台添加android

    然后我创建了一个用于测试目的的sqlite数据库,命名为 mydb.sqlite 包含两个 id firstname lastname 记录。



    我决定使用以下插件: https://github.com/Antair/Cordova- SQLitePlugin
    这是因为它可以用cordova工具安装。

      ionic插件添加https:// github.com/Antair/Cordova-SQLitePlugin 

    警告:网站显示不正确的参考 - cordova插件添加 https://github.com/brodysoft/Cordova-SQLitePlugin - 指另一个插件)。



    然后,按照插件网站上的说明, / www / db / ,以便现在可以在 myapp / www / db / mydb.sqlite

    中找到

    脚本之后的 index.html 包括SQLite插件:

     <! - 您的应用程式的js  - > 
    < script src =js / app.js>< / script>
    < script src =SQLitePlugin.js>< / script>

    我还在 index.html 文件中写了一些代码行a button:

     < ion-content ng-controller =MyCtrl> 
    < button class =buttonng-click =all()>全部< / button>
    < / ion-content>



    最后我修改了./ js / app.js : p>

      // Ionic Starter App 

    var db = null;

    angular.module('starter',['ionic'/ *这里是什么?* /])

    .run(function($ ionicPlatform){
    $ ionicPlatform.ready(function(){
    //一些预定义的代码已被省略

    window.sqlitePlugin.importPrepopulatedDatabase({file:mydb.sqlite,importIfExists:true });
    db = window.sqlitePlugin.openDatabase({name:mydb.sqlite});

    }); // $ ionicPlatform.ready
    })/ / .run

    .controller('MyCtrl',function($ scope){

    $ scope.all = function(){
    var query =SELECT * FROM people;
    //我不知道如何继续

    }; // $ scope.all

    }); // .controller

    ___ 问题



    我不知道如何继续在控制器部分查询所有的记录(只是一个查询的例子),并在console.log中显示结果。



    我认为以下代码必须以某种方式完成:

      angular.module ',['ionic'/ *这里是什么?* /])

    控制器部分必须完成:

      $ scope.all = function(){
    var query =SELECT * FROM人;
    //我不知道如何进行

    }; // $ scope.all

    ___ FINAL THANKS



    感谢您提供给我的帮助。

    解决方案

    家伙的代码帮助了很多封装我的DAL。我强烈建议你使用他的代码非常详尽。



    https://gist.github.com/jgoux/10738978



    您会看到他有以下方法:

      self.query = function(query,bindings){
    bindings = typeof bindings!=='undefined'? bindings:[];
    var deferred = $ q.defer();

    self.db.transaction(function(transaction){
    transaction.executeSql(query,bindings,function(transaction,result){
    deferred.resolve(result);
    },function(transaction,error){
    deferred.reject(error);
    });
    });

    return deferred.promise;
    };

    让我们来分析一下。查询函数接受查询字符串(查询参数)和可能的绑定列表?在类似SELECT * FROM A_TABLE WHERE ID =?的查询中。因为他的代码是一个服务,自我价值指向服务本身为所有未来的调用。该函数将对db执行一个事务,但它返回的promise只有在db返回后才会被执行。



    他的服务提供了第二个辅助函数:fetchAll。

      self.fetchAll = function(result){
    var output = [];

    for(var i = 0; i output.push(result.rows.item(i));
    }

    返回输出;
    };

    fetchAll会将这些行全部读入数组。 fetchAll的结果参数是在查询函数的promise履行中传递的结果变量。



    如果将其代码复制并粘贴到服务文件中,则现在有一个bonafide DB服务。您可以将该服务包装在DAL中。这是我的项目的一个例子。

      .service('LocationService',function($ q,DB,Util){
    'use strict';
    var self = this;
    self.locations = [];
    self.loadLocked = false;
    self.pending = [];

    self.findLocations = function(){
    var d = $ q.defer();
    if(self.locations.length> 0){
    d。 (self.locations);
    }
    else if(self.locations.length === 0&&!self.loadLocked){
    self.loadLocked = true;
    DB.query(SELECT * FROM locations WHERE kind ='active')
    .then(function(resultSet){
    var locations = DB.fetchAll(resultSet);
    self .locations。
    push.apply(self.locations,locations);
    self.loadLocked = false;
    d.resolve(self.locations);
    self.pending.forEach (function(d){
    d.resolve(self.locations);
    });
    },Util.handleError);
    } else {
    self.pending.push(d);
    }

    return d.promise;
    };
    })

    这个例子有点嘈杂,因为它有一些线程代码确保相同的promise被触发两次,它只对DB运行一次。一般的意思是显示DB.query返回一个promise。查询方法之后的then使用DB服务来获取所有数据并将其添加到我的本地内存空间中。所有这些都由self.findLocations返回变量d.promise协调。



    您的代表同样。控制器可以具有您的DAL服务,如我的LocationService,注入到AngularJS。如果您使用AngularJS UI,您可以让它解析数据并将其传递到列表中。



    最后,我对这个人的代码唯一的问题是db应该来自这个代码。

      var dbMaker =($ window.sqlitePlugin || $ window); 

    这样做的原因是插件在Apache Ripple中不工作。由于插件在镜像Web浏览器的SQL接口,这个简单的小改变将使Ripple运行您的Ionic应用程序,同时仍然允许您在真实的设备中工作您的SQLite。



    我希望这有助于。


    ____ INTRO

    Hello everyone, first of all, three clarifications:

    1. My english is not good, so I beg your pardon in advance for my mistakes,
    2. I'm a newbie so forgive me for inaccuracies,
    3. I have previously searched and tried the solutions I found on the internet but still I can not solve the problem of embedding a prepopulated database.

    ____ THE GOAL

    I want to develop an app for iOS and Android with a prepopulated database.

    Just for example, the database consists of 15.000 records each one made of three key-value pair (id, firstname and lastname).

    ___ WHAT I DID

    Steps:

    ionic start myapp blank
    cd myapp
    ionic platform add ios
    ionic platform add android
    

    Then I created an sqlite database for testing purpose, named mydb.sqlite, made of one table people containing two id, firstname, lastname records.

    I decided to use the following plugin: https://github.com/Antair/Cordova-SQLitePlugin That's because it can be installed with cordova tool.

    ionic plugin add https://github.com/Antair/Cordova-SQLitePlugin
    

    (Alert: I think that the instructions on the website show an incorrect reference - "cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin" - which refers to another plugin).

    Then, following the instructions on the plugin website, I copied the database to myapp/www/db/ so that it can now be found at myapp/www/db/mydb.sqlite

    I modified the index.html including the SQLite plugin just after the default app.js script:

    <!-- your app's js -->
    <script src="js/app.js"></script>
    <script src="SQLitePlugin.js"></script>
    

    I also write some lines of code in index.html file to show a button:

    <ion-content ng-controller="MyCtrl">
        <button class="button" ng-click="all()">All</button>
    </ion-content>
    

    Finally I had modified ./js/app.js:

    // Ionic Starter App
    
    var db = null;
    
    angular.module('starter', ['ionic' /* What goes here? */ ])
    
    .run(function($ionicPlatform) {
      $ionicPlatform.ready(function() {
        // some predefined code has been omitted
    
        window.sqlitePlugin.importPrepopulatedDatabase({file: "mydb.sqlite", "importIfExists": true});
        db = window.sqlitePlugin.openDatabase({name: "mydb.sqlite"});
    
      }); // $ionicPlatform.ready
    }) // .run
    
    .controller('MyCtrl', function($scope){
    
        $scope.all = function(){
                var query = "SELECT * FROM people";
                // I don't know how to proceed
    
        }; // $scope.all
    
    }); // .controller
    

    ___ THE PROBLEM

    I don't know how to proceed in the controller section to query all the records (just an example of query) and show the results in the console.log.

    I think that the following code must be completed in some way:

    angular.module('starter', ['ionic' /* What goes here? */ ]) 
    

    And also the code inside controller section must be completed:

           $scope.all = function(){
                    var query = "SELECT * FROM people";
                    // I don't know how to proceed
    
            }; // $scope.all
    

    ___ FINAL THANKS

    Thank you in advance for the help you will give to me.

    解决方案

    So this guy's code has helped a lot to encapsulate my DAL. I highly recommend that you use he's code pretty much verbatim.

    https://gist.github.com/jgoux/10738978

    You'll see he has the following method:

    self.query = function(query, bindings) {
        bindings = typeof bindings !== 'undefined' ? bindings : [];
        var deferred = $q.defer();
    
        self.db.transaction(function(transaction) {
            transaction.executeSql(query, bindings, function(transaction, result) {
                deferred.resolve(result);
            }, function(transaction, error) {
                deferred.reject(error);
            });
        });
    
        return deferred.promise;
    };
    

    Let's break this down a bit. The query function takes a query string (the query param) and a list of possible bindings for ? in a query like "SELECT * FROM A_TABLE WHERE ID = ?". Because he's code is a service, the self value points to the service itself for all future invocations. The function will execute a transaction against the db, but it returns a promise that is only fulfilled once the db comes back.

    His service provides a second helper function: fetchAll.

    self.fetchAll = function(result) {
        var output = [];
    
        for (var i = 0; i < result.rows.length; i++) {
            output.push(result.rows.item(i));
        }
    
        return output;
    };
    

    fetchAll will read the rows in their entirety into an array. The result param for fetchAll is the result variable passed in the query function's promise fulfillment.

    If you copy and paste his code into your service file, you now have a bonafide DB service. You can wrap that service up in a DAL. Here's an example from my project.

    .service('LocationService', function ($q, DB, Util) {
        'use strict';
        var self = this;
        self.locations = [];
        self.loadLocked = false;
        self.pending = [];
    
        self.findLocations = function () {
            var d = $q.defer();
            if (self.locations.length > 0) {
                d.resolve(self.locations);
            }
            else if (self.locations.length === 0 && !self.loadLocked) {
                self.loadLocked = true;
                DB.query("SELECT * FROM locations WHERE kind = 'active'")
                       .then(function (resultSet) {
                           var locations = DB.fetchAll(resultSet);
                           self.locations.
                               push.apply(self.locations, locations);
                           self.loadLocked = false;
                           d.resolve(self.locations);
                           self.pending.forEach(function (d) {
                               d.resolve(self.locations);
                           });
                       }, Util.handleError);
                } else {
                    self.pending.push(d);
                }
    
                return d.promise;
            };
    })
    

    This example is a bit noisy since it has some "threading" code to make sure if the same promise is fired twice it only runs against the DB once. The general poin is to show that the DB.query returns a promise. The "then" following the query method uses the DB service to fetchAll the data and add it into my local memory space. All of this is coordinated by the self.findLocations returning the variable d.promise.

    Yours would behalf similarly. The controller could have your DAL service, like my LocationService, injected into it by AngularJS. If you're using the AngularJS UI, you can have it resolve the data and pass it into the list.

    Finally, the only issue I have with the guy's code is that the db should come from this code.

    var dbMaker = ($window.sqlitePlugin || $window);
    

    The reason for this is that the plugin does not work within Apache Ripple. Since the plugin does a fine job mirroring the Web SQL interface of the browser, this simple little change will enable Ripple to run your Ionic Apps while still allowing you to work your SQLite in a real device.

    I hope this helps.

    这篇关于安卓Cordova的离线预填数据库SQLitePlugin [帮助请求]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆