2014-06-19 2 views
0

i18n 앱을 쓰려고합니다. 이 프로그램은 json 파일을 읽었습니다. json 파일에는 json 구조를 기반으로하는 언어와 번역이 들어 있습니다. , 다트 비동기 방식으로여러 번 파일을 읽지 못하게하기

{ 
    "EN": { 
     "TEXT1": "Hello", 
     "TEXT2": "March" 
    }, 
    "DE": { 
     "TEXT1": "Hallo", 
     "TEXT2": "März" 
    } 
} 

내 프로그램이 파일 클래스와 비동기 방식으로 JSON 파일, 전체 코드

import 'dart:io'; 
import 'dart:async'; 
import 'package:json_object/json_object.dart'; 

abstract class I18n { 

    static _I18n _i18n; 

    factory I18n(String file, String lang) { 
     if(_i18n == null) { 

      _i18n = new _I18n(file, lang); 
      return _i18n; 
     } 

     return _i18n; 
    } 


    Future<String> getTextByMap(String textId); 

} 

class _I18n implements I18n { 

    File _file; 
    String _lang; 
    JsonObject _jsonContainer; 
    JsonObject _jsonFiltered; 
    Future<JsonObject> _imme; 

    // Parameters: 
    // file: The whole path and filename 
    // lang: Expected language 
    _I18n(String file, this._lang) { 
     this._file = new File(file); 
    } 

    // Read file and return the content of file. 
    Future<String> _readFileFromStream() { 
     var com = new Completer(); 
     this._file.exists() 
      .then((fileExists) { 

       if(!fileExists) { 
        throw new StateError('File not found'); 
       } 
       return this._file.readAsString() 
        .then((stream) => com.complete(stream)); 
      }); 
     return com.future; 
    } 

    void _convertContentToJson(String stream) { 
     this._jsonContainer = new JsonObject.fromJsonString(stream); 
    } 


    Future<JsonObject> _prepareData() { 
     return this._readFileFromStream().then((stream) { 
      _convertContentToJson(stream); 
      this._jsonFiltered = this._jsonContainer[this._lang]; 
      return this._jsonFiltered; 
     }); 
    } 


    Future<String> getTextByMap(String textId) { 
     return this._prepareData().then((filterd) { 
      return filterd[textId]; 
     }); 
    } 
} 

import 'package:i18n/i18n.dart'; 


void main() { 
    var i18n = new I18n('../hello.json', 'EN'); 
    i18n.getTextByMap('TEXT1').then((val) => print(val)); 
    i18n.getTextByMap('TEXT2').then((val) => print(val)); 
} 

모두 여기에 주요 코드를 읽을 일이 , json 파일 등을 읽습니다. 그리고 매번 메소드를 호출 할 때

i18n.getTextByMap('TEXT1').then((val) => print(val)); 

그러면 json 파일을 계속해서 읽을 것입니다. json 파일을 여러 번 읽지 못하도록하는 방법을 다시 작성하려고 시도했습니다.

Future<String> getTextByMap(String textId) { 
    if(this._jsonFiltered == null) 
    { 
     return this._prepareData().then((filterd) { 
      return filterd[textId]; 
     }); 
    } 
    return new Future(() => this._jsonFiltered[textId]); 
} 

그러나 다트가 비동기 방식으로 작동하기 때문에 작동하지 않습니다.

제 질문은 어떻게이 json 파일 내용을 객체에 보관할 수 있습니까? json 파일을 한 번만 읽고 객체의 내용을 유지하십시오. 매번 json 파일을 읽는 것이 좋습니다. 이것이 제 의견입니다.

그것은 동기화 방식으로 모든 것을 할 수 있습니다. 그렇다면 문제는 없지만 이것은 다트 용어가 아닙니다.

다트가 어느 순서로 I/O 작업을 실행합니까?

  1. 미래
  2. I/O 이벤트

답변

3

내 솔루션은 공장 생성자를 가진 클래스를 생성하는 것입니다. 팩토리 생성자는 항상 해당 파일의 객체를 반환합니다.

당신의 문제는 미래가 평행하다는 것입니다. 그래서 두 호출은 병렬로 실행됩니다. 해결책은 첫 번째 미래를 완료 한 다음 캐시 된 결과를 얻을 수있는 다른 작업을 수행하는 것입니다.

예를 들어 class "contents"속성에없는 경우 파일의 값을 읽는 read() 메소드를 사용할 수 있습니다. 또는 해당 속성이 null이 아닌 경우 백그라운드에서 파일을로드합니다.

두 경우 모두 완성자 또는 미래가 반환되므로들을 수 있습니다.

편집 예제 코드 :

example_async_file_factory.다트

import 'dart:io'; 
import 'dart:async'; 

class FileHolder { 
    String _contents = null; 

    String path; 

    static Map<String, FileHolder> _files; 

    factory FileHolder(String path) { 
    if (_files == null) { 
     _files = {}; 
    } 

    if (_files.containsKey(path)) { 
     return _files[path]; 
    } else { 
     final fh = new FileHolder._internal(path); 
     _files[path] = fh; 
     return fh; 
    } 
    } 

    FileHolder._internal(this.path); 

    Future<String> getContents() { 
    if(_contents != null) { 
     print("cached"); 
     return new Future.value(_contents); 
    } else { 
     print("read"); 
     File f = new File(this.path); 
     Future<String> future = f.readAsString(); 
     Completer completer = new Completer(); 
     future.then((String c) { 
     _contents = c; 
     completer.complete(_contents); 
     }); 
     return completer.future; 
    } 
    } 
} 

void main() { 
    FileHolder f = new FileHolder("example_async_file_factory.dart"); 
    f.getContents().then((String contents) { 
    print(contents.length); 

    FileHolder f2 = new FileHolder("example_async_file_factory.dart"); 
     f2.getContents().then((String contents) { 
     print(contents.length); 
     }); 
     f2.getContents().then((String contents) { 
      print(contents.length); 
     }); 
     f.getContents().then((String contents) { 
      print(contents.length); 
     }); 
    }); 
} 

출력 :

read 
1411 
cached 
cached 
cached 
1411 
1411 
1411 

감사 로버트

내가 Completer`는 getContents``에 불필요`생각
+0

같은 결과 등의 변형 제공 : 미래 getContents를() { if (_contents! = null) { 인쇄 ("캐시 됨"); return new Future.value (_contents); } else { 인쇄 ("읽기"); 파일 f = 새 파일 (this.path); return f.readAsString(). ((String c) { _contents = c; return c; }); } } } –

+0

네, 맞습니다. Vadim. 이것도 효과가있다. – Robert

관련 문제