J'essaie de créer un widget app pour mon application et d'afficher la liste des favoris dans le widget app. Cependant, il indique l'erreur: «accès à l'espace de fil incorrect des objets de royaume ne peuvent être accessibles sur le fil, ils ont été créés. »Comment résoudre "Accès au domaine depuis un thread incorrect Les objets du domaine ne sont accessibles que sur le thread qu'ils ont été créés"
FATAL EXCEPTION: Binder:3017_3
Process: com.santossingh.capstoneproject, PID: 3017
java.lang.IllegalStateException: Realm access from incorrect thread. Realm objects can only be accessed on the thread they were created.
at io.realm.BaseRealm.checkIfValid(BaseRealm.java:353)
at io.realm.RealmResults.isLoaded(RealmResults.java:88)
at io.realm.OrderedRealmCollectionImpl.size(OrderedRealmCollectionImpl.java:303)
at io.realm.RealmResults.size(RealmResults.java:53)
at com.santossingh.capstoneproject.Widget.ListProvider.getCount(ListProvider.java:57)
at android.widget.RemoteViewsService$RemoteViewsFactoryAdapter.getCount(RemoteViewsService.java:154)
at com.android.internal.widget.IRemoteViewsFactory$Stub.onTransact(IRemoteViewsFactory.java:75)
at android.os.Binder.execTransact(Binder.java:565)
03-31 20:32:01.058 1298-1458/? E/SurfaceFlinger: ro.sf.lcd_density must be defined as a build property
Si vous en savez s'il vous plaît me donner un exemple clair sur les données d'accès à d'autres activités ou comment appeler thread particulier où la base de données de domaine créé.
1- ConfigActivity
public class ConfigActivity extends AppCompatActivity {
private int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
Realm realm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_config);
Realm.init(this);
RealmConfiguration config = new RealmConfiguration.Builder()
.deleteRealmIfMigrationNeeded()
.build();
realm=Realm.getInstance(config);
assignAppWidgetId();
startWidget();
}
/**
* Widget configuration activity,always receives appwidget Id appWidget Id =
* unique id that identifies your widget analogy : same as setting view id
* via @+id/viewname on layout but appwidget id is assigned by the system
* itself
*/
private void assignAppWidgetId() {
Bundle extras = getIntent().getExtras();
if (extras != null)
appWidgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
}
/**
* This method right now displays the widget and starts a Service to fetch
* remote data from Server
*/
private void startWidget() {
// this intent is essential to show the widget
// if this intent is not included,you can't show
// widget on homescreen
Intent intent = new Intent();
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
setResult(Activity.RESULT_OK, intent);
// start your service
// to fetch data from web
Intent serviceIntent = new Intent(this, ListProvider.class);
serviceIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
startService(serviceIntent);
// finish this activity
this.finish();
}
2- classe ListProvider
public class ListProvider implements RemoteViewsService.RemoteViewsFactory {
private MyHandlerThread mHandlerThread=new MyHandlerThread();
private Context context = null;
private int appWidgetId;
RealmResults<FavoriteBooks> booksList;
RealmConfiguration config;
public ListProvider(Context context, Intent intent) {
this.context = context;
appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
getDataFromRealm(context);
}
@Override
public void onCreate() {
}
@Override
public void onDataSetChanged() {
getDataFromRealm(context);
}
@Override
public void onDestroy() {
}
@Override
public int getCount() {
return booksList.size();
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public RemoteViews getViewAt(final int position) {
final Lock lock = new Lock();
final RemoteViews[] result = {null};
mHandlerThread.getHandler().post(new Runnable() {
@Override
public void run() {
// You can safely access results here.
result[0] = new RemoteViews(context.getPackageName(), R.layout.widget_item);
if (booksList!=null) {
FavoriteBooks book = booksList.get(position);
result[0].setTextViewText(R.id.widgetText, book.getTitle());
}
lock.unlock();
}
});
try {
lock.lock();
} catch (InterruptedException e) {
e.printStackTrace();
}
return result[0];
}
@Override
public RemoteViews getLoadingView() {
return null;
}
@Override
public int getViewTypeCount() {
return 0;
}
//------------
public class Lock {
private boolean isLocked;
public synchronized void lock() throws InterruptedException {
isLocked = true;
while (isLocked) {
wait();
}
}
public synchronized void unlock() {
isLocked = false;
notify();
}
}
public class MyHandlerThread extends HandlerThread {
private Handler mHandler;
public MyHandlerThread() {
super("MY_HANDLER_THREAD");
start();
mHandler = new Handler(getLooper());
}
public Handler getHandler() {
return mHandler;
}
}
private void getDataFromRealm(final Context context) {
final Lock lock = new Lock();
mHandlerThread.getHandler().post(new Runnable() {
@Override
public void run() {
Realm.init(context);
config = new RealmConfiguration.Builder()
.name("favorite1.realm")
.schemaVersion(1)
.deleteRealmIfMigrationNeeded()
.build();
Realm realm = Realm.getInstance(config);
booksList = realm.where(FavoriteBooks.class).findAll();
lock.unlock();
}
});
try {
lock.lock();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3- classe WidgetService
public class WidgetService extends RemoteViewsService {
/*
* So pretty simple just defining the Adapter of the listview
* here Adapter is ListProvider
* */
@Override
public RemoteViewsFactory onGetViewFactory(Intent intent) {
int appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
// call and return listprovider class
return (new ListProvider(this.getApplicationContext(), intent));
}
}
4- WidgetProvider classe
public class WidgetProvider extends AppWidgetProvider {
public final static String DATA_FETCHED="com.santossingh.capstoneproject.DATA_FETCHED";
@Override
public void onUpdate(Context context, AppWidgetManager
appWidgetManager, int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i = 0; i < N; ++i) {
RemoteViews remoteViews = updateAppWidget(context,
appWidgetIds[i]);
appWidgetManager.updateAppWidget(appWidgetIds[i],
remoteViews);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
private RemoteViews updateAppWidget(Context context, int appWidgetId) {
//which layout to show on widget
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
//RemoteViews Service needed to provide adapter for ListView
Intent svcIntent = new Intent(context, WidgetService.class);
//passing app widget id to that RemoteViews Service
svcIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
//setting a unique Uri to the intent
//don't know its purpose to me right now
svcIntent.setData(Uri.parse(
svcIntent.toUri(Intent.URI_INTENT_SCHEME)));
//setting adapter to gridView of the widget
remoteViews.setRemoteAdapter(appWidgetId, R.id.gridViewWidget,
svcIntent);
//setting an empty view in case of no data
remoteViews.setEmptyView(R.id.gridViewWidget, R.id.emptyTextViewWidget);
return remoteViews;
}
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
if (intent.getAction().equals(DATA_FETCHED)) {
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = updateAppWidget(context, appWidgetId);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
}
}
5- RemoteFetchService classe
public class RemoteFetchService extends Service {
private int appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
/**
* Retrieve appwidget id from intent it is needed to update widget later
* initialize our AQuery class
*/
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (intent.hasExtra(AppWidgetManager.EXTRA_APPWIDGET_ID))
appWidgetId = intent.getIntExtra(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
populateWidget();
return super.onStartCommand(intent, flags, startId);
}
/**
* Method which sends broadcast to WidgetProvider
* so that widget is notified to do necessary action
* and here action == WidgetProvider.DATA_FETCHED
*/
private void populateWidget() {
Intent widgetUpdateIntent = new Intent();
widgetUpdateIntent.setAction(WidgetProvider.DATA_FETCHED);
widgetUpdateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
appWidgetId);
sendBroadcast(widgetUpdateIntent);
this.stopSelf();
}
6- FavoriteBooks classe étend RealmObject
public class FavoriteBooks extends RealmObject {
@PrimaryKey
private String id;
private String title;
private String author;
private String buyLink;
private String image;
private String price;
private String publishedDate;
private String reviewLink;
private String description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getBuyLink() {
return buyLink;
}
public void setBuyLink(String buyLink) {
this.buyLink = buyLink;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getPublishedDate() {
return publishedDate;
}
public void setPublishedDate(String publishedDate) {
this.publishedDate = publishedDate;
}
public String getReviewLink() {
return reviewLink;
}
public void setReviewLink(String reviewLink) {
this.reviewLink = reviewLink;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getPrice() {
return price;
}
public void setPrice(String price) {
this.price = price;
}
}
Alors S'il vous plaît aidez-moi ... Ce serait génial si vous pouviez corriger mes ListProvider.class où que les émissions d'erreur sur
@Override
public int getCount() {
return booksList.size();
}
Exception stacktrace .... – EpicPandaForce
vérifier, j'ai ajouté –
Je pense qu'il ya une chance que Widget UI s'exécute dans un processus * distinct * – EpicPandaForce