1

コードバ 2.2.0 を使用して eclipse で Android アプリを開発しています。Phonegap のファイル API を取得しているようですが、ファイルの読み書きはできません。

iOS用のアプリを完成させたxcodeからスクリプトをコピーしましたが、動作します。

コンソール出力でトレースされた私のスクリプトは次のとおりです。

window.onload = function (){
    console.log('1: onload');
    document.addEventListener("deviceready", getSettings, false);
}
function getSettings(){
    console.log('2: getSettings()');
    fileSys('settings.txt', 'getContent', null);
    //fileSys('settings.txt', 'replaceContent', 'new settings');
}
function fileSys(fileName, action, data){
    console.log('3: fileSys - '+fileName+' - '+action);
    var directory = (fileName == 'sidur') ? 'appin/sidur':'appin';
    window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);
    function gotFS(fileSystem) {
    console.log('4: Got file system, get directory...');
    fileSystem.root.getDirectory(directory, {create: true}, gotDir, fail);
    }
    function gotDir(dirEntry) {
        console.log('5: Got directory. Get file...');
        dirEntry.getFile(fileName, {create: true, exclusive: false}, gotFileEntry, fail);
    }
    function gotFileEntry(fileEntry){
        console.log('6: got file. Perform action: '+action+'...');
        if(action == 'getContent') readAsText(fileEntry);
        if(action == 'replaceContent') fileEntry.createWriter(gotFileWriter, fail);
    }
    function gotFileWriter(writer){
        console.log('7: got file writer...');
        writer.write(data); //function variable of fileSys();
        writer.onwriteend = function(evt) {
        console.log('8: file written');
        };
    }
    function readAsText(file) {
        console.log('7: read as text...');
        var reader = new FileReader();
        reader.readAsText(file);
        reader.onloadend = function(evt) {
            console.log('9: done reading file');
            init(evt.target.result);
        }
    }
    function fail(error){
        console.log('fail: '+error.code);

    }
}
function init(settings){
    console.log('Init. Settings: '+JSON.stringify(settings));
}

このスクリプトを実行すると、次のコンソール出力が得られます。

  • 1: オンロード
  • 2: getSettings()
  • 3: fileSys - settings.txt - getContent
  • 4: ファイルシステムを取得し、ディレクトリを取得...
  • 5: ディレクトリを取得しました。ファイルを取得...
  • 6: ファイルを取得しました。アクションを実行: getContent...
  • 7: テキストとして読む...

そして、そこで止まります。reader.onloadend は呼び出されず、エラーは指定されません。もう一度実行すると、代わりに fileSys('settings.txt', 'replaceContent', 'new settings'); を呼び出します。fileSys への他の呼び出しをアウトコメントすると、コンソールは次のように出力します。

  • 1: オンロード
  • 2: getSettings()
  • 3: fileSys - settings.txt - replaceContent
  • 4: ファイルシステムを取得し、ディレクトリを取得...
  • 5: ディレクトリを取得しました。ファイルを取得...
  • 6: ファイルを取得しました。アクションを実行: replaceContent...
  • 7: ファイルライターを取得しました...

私は持っている:

  • res/config.xml と android manifest.xml で正しい権限/プラグインを設定します
  • Phonegap API が含まれており、機能していることを確認しました (通知あり)

私は日食だけでなくアプリ開発も初めてなので、これは私が見逃した基本的なことかもしれません。どんな提案や指針も大歓迎です。

4

2 に答える 2

2

了解しました。これを理解しました。問題は私のコードの構造にありました。

これはiOSで正常に機能します:

function readAsText(file) {
    var reader = new FileReader();
    reader.readAsText(file);
    reader.onloadend = function(evt) {
        console.log('9: done reading file');
        init(evt.target.result);
    };
}

しかし、どういうわけか、Androidのphonegapでは、リーダーのreadAsTextメソッドの上にリーダーのonloadendメソッドの変数を宣言する必要があります。そのようです:

function readAsText(file) {
    var reader = new FileReader();
    reader.onloadend = function(evt) {
        console.log('9: done reading file');
        init(evt.target.result);
    };
    reader.readAsText(file);
}

振り返ってみると、これは私には完全に理にかなっています。iOSが他の方法を許可しているのは奇妙に思えます。

于 2012-11-18T19:21:07.733 に答える
1

実際には、Android と iOS の両方が同じ順序でステートメントを解釈するため、ステートメントの順序ではありません。異なるのは、readAsText の作業が別のスレッドで非同期に行われるため、完了する速度です。iOS で発生した例を次に示します。

reader.readAsText - this starts the read process in another thread
reader.onloadend = function... - you set up your handler
-- on separate thread, readAsText finally completes and sees your handler and calls it

これはAndroidで起こったことです:

reader.readAsText - this starts the read process in another thread
-- on separate thread, readAsText completed quickly but your handler has not been set yet so it does not get called
reader.onloadend = function... - you set up your handler too late, the read already completed in its own thread

非同期呼び出しでは、他のタスクがいつ完了するかを保証できません。これは Android と iOS の違いではなく、マルチスレッド操作の性質によるものです。非同期呼び出しを処理するには、さまざまな方法があります (コールバックを適切に並べ替えてネストする、jquery deferred を使用する、何らかの種類のセマフォ メカニズムなどを使用するなど)。重要なことは、タスクが特定の時間内に完了することに決して依存したり、想定したりしないことです。タイミングへの依存はあなたを苦しめる可能性があり、デバッグが非常に困難です。

于 2013-03-12T15:53:49.187 に答える