Tôi muốn tiêm một singleton SqliteOpenHelper
vào một số ContentProvider
. Tuy nhiên, có vẻ như cá thể ContentProvider
đang được tạo trước khi cá thể Ứng dụng đang được tạo (getApplicationContext()
trả về null). Khi nào tôi có thể tiêm cơ sở dữ liệu? Tôi đã thử trong hàm tạo và trong phương thức onCreate()
của ContentProvider
.Tiêm cơ sở dữ liệu trong Trình ContentProvider với dao găm
Trả lời
Tôi phải đối mặt với cùng một vấn đề và phải trì hoãn việc tiêm cho đến khi có cơ sở dữ liệu. Bạn có thể sử dụng lazy injection của Dagger để đạt được hiệu quả tương tự.
Từ nhà cung cấp nội dung của onCreate documentation:
Bạn nên trì hoãn việc khởi tạo không tầm thường (ví dụ như mở cửa, nâng cấp, và cơ sở dữ liệu quét) cho đến khi các nhà cung cấp nội dung được sử dụng
Rõ ràng đề nghị này không thể bỏ qua . Implementing the onCreate() method cung cấp một ví dụ bằng cách sử dụng một SQLiteOpenHelper với một nhà cung cấp nội dung.
Như Alex Baker đã chỉ ra, giải pháp của vấn đề là trì hoãn việc tiêm khi một hoạt động (truy vấn, chèn, cập nhật, xóa) được gọi lần đầu tiên.
để làm một ví dụ:
này sẽ không làm việc:
public class YourProviderNull extends ContentProvider {
@Inject
YourSQLHelper yourHelper;
@Override
public boolean onCreate() {
YourActivity.getComponent().inject(this); //NPE!!!
//other logic
return true;
}
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
SQLiteDatabase db = yourHelper.getReadableDatabase();
//other logic
}
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
SQLiteDatabase db = yourHelper.getWritableDatabase();
//other logic
}
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
SQLiteDatabase db = yourHelper.getWritableDatabase();
//other logic
}
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = yourHelper.getWritableDatabase();
//other logicreturn db.update(resolveTableNameForUri(uri), values, selection, selectionArgs);
}
}
nhưng điều này sẽ làm việc một cách chính xác:
public class YourProviderWorking extends ContentProvider {
@Inject
YourSQLHelper yourHelper;
@Override
public boolean onCreate() {
//other logic
return true;
}
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
if(yourHelper == null){
deferInit();
}
SQLiteDatabase db = yourHelper.getReadableDatabase();
//other logic
}
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
if(yourHelper == null){
deferInit();
}
SQLiteDatabase db = yourHelper.getWritableDatabase();
//other logic
}
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
if(yourHelper == null){
deferInit();
}
SQLiteDatabase db = yourHelper.getWritableDatabase();
//other logic
}
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
if(yourHelper == null){
deferInit();
}
SQLiteDatabase db = yourHelper.getWritableDatabase();
//other logicreturn db.update(resolveTableNameForUri(uri), values, selection, selectionArgs);
}
private void deferInit(){
YourActivity.getComponent().inject(this);
}
}
Đây là thông tin chi tiết tuyệt vời. Bạn cũng có thể làm điều kiện bên trong deferInit() và bạn chỉ cần thực hiện một lời gọi phương thức ở khắp mọi nơi. –
Simple Soluti trên
Có một lý do đơn giản cho việc này, nhà cung cấp
onCreate()
được gọi là trước phương pháp thích hợp trong Đơn đăng ký. Bạn có thể tạo một thành phần theo phương pháp khác của ứng dụng , ví dụ:attachBaseContext
.
Di chuyển logic của bạn từ onCreate
để attachBaseContext
trong ứng dụng của bạn.
@Override
public void attachBaseContext(Context base){
super.attachBaseContext(base);
mApplicationComponent = DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.build();
mApplicationComponent.inject(this);
}
Bạn có thể bây giờ inject
trong OnCreate
trong ContentProvider của bạn:
public boolean onCreate() {
YourMainApplication.get(getContext()).getComponent().inject(this);
return true;
}
Disclaimer: Tín Full để @LeEnot từ blog Nga này: Dagger2 Inject in Content Provider. Câu trả lời được liệt kê ở đây để thuận tiện vì nó không có sẵn bằng tiếng Anh.
Đây là cách tiếp cận tốt nhất. Tôi đã sử dụng một trong những đầu, và tại thời điểm thành phần là null, sau đó gây ra một lỗi 'Gây ra bởi: java.lang.NullPointerException: Cố gắng gọi phương thức giao diện 'void thông tin .... LiteComponent.inject (thông tin .... .LiteContentProvider) 'trên tham chiếu đối tượng null' –
- 1. dao găm không thể tiêm loại tham số lĩnh vực
- 2. dao găm 2 tròn dependancy
- 3. Tạo dao găm YAML từ JSDoc?
- 4. Trình bày không giới hạn trong cơ sở dữ liệu với kiểu dữ liệu số
- 5. Bỏ phiếu dài với dữ liệu cơ sở dữ liệu?
- 6. neo4j - đồ thị cơ sở dữ liệu cùng với một cơ sở dữ liệu quan hệ?
- 7. Chia nhỏ tệp mysqldump với nhiều cơ sở dữ liệu, theo cơ sở dữ liệu
- 8. Mẫu nhà máy cơ sở dữ liệu với nhiều cơ sở dữ liệu
- 9. Heroku với Cơ sở dữ liệu H2
- 10. Tạo cơ sở dữ liệu với JPA?
- 11. Cơ sở dữ liệu lớn trong lập trình chức năng
- 12. Lược đồ cơ sở dữ liệu so với vùng bảng cơ sở dữ liệu?
- 13. Xóa cơ sở dữ liệu khi Tài khoản bị xóa
- 14. Làm thế nào để tiêm cơ sở dữ liệu vào hàm tạo với Laravel IoC
- 15. Cơ sở dữ liệu xuất MSSQL với dữ liệu
- 16. Làm mới/Nạp lại cơ sở dữ liệu tham khảo trong ContentProvider tùy chỉnh sau khi khôi phục
- 17. Tạo dữ liệu thử nghiệm trong cơ sở dữ liệu
- 18. IllegalStateException: Các bảng không hợp lệ khi cố gắng truy vấn cơ sở dữ liệu với ContentProvider
- 19. mangento trong cơ sở dữ liệu hoặc cơ sở oracle?
- 20. Nhiều cơ sở dữ liệu trong Rails
- 21. Chuyển dữ liệu từ cơ sở dữ liệu này sang cơ sở dữ liệu khác
- 22. Cơ sở dữ liệu CUBRID
- 23. Chèn phụ thuộc vào CustomView với dao găm 2 (trong phạm vi hoạt động)
- 24. Lỗi khi kéo cơ sở dữ liệu mysql trong cơ sở dữ liệu mysql cục bộ
- 25. cơ sở dữ liệu node.js
- 26. Ngăn chặn việc tiêm SQL trong một lớp cơ sở dữ liệu
- 27. Nhiều cơ sở dữ liệu trong Ecto
- 28. Visual studio không thể thêm tệp siêu dữ liệu dao găm trong ứng dụng khách api còn lại của tôi
- 29. Tài liệu cơ sở dữ liệu Postgresql
- 30. Java, cách thay đổi cơ sở dữ liệu hiện tại sang cơ sở dữ liệu khác?
bạn có thể vui lòng nói cách bạn trì hoãn việc tiêm, tôi đã cố gắng tiêm lớp Ứng dụng của tôi có tham chiếu đến cơ sở dữ liệu sqlite không có kết quả. đã thử tiêm nó khi gọi các phương thức chèn, truy vấn, vv của nhà cung cấp nội dung mà không thành công và việc tiêm trường sẽ không hoạt động. – irobotxxx
@sparrow Bạn có thể thêm các trường lười vào nhà cung cấp nội dung của bạn, tiêm chúng vào onCreate và sử dụng phương thức get() trên trường lười bên trong chèn, truy vấn, v.v. Đây là ví dụ từ ứng dụng của tôi https://github.com /tasks/tasks/blob/7ff1ba5fbe9aa851f1e7d003c415c7463945ffcc/src/main/java/com/todoroo/astrid/provider/Astrid3ContentProvider.java –