Issue
I am writing an android app using only web view and web interfaces. I have a Navigation Drawer with menu items, and I need to change menu itens visibility for different types of users (f.e moderator, seller etc.). And For that I call setItemVisible() function in js from WebInterface, but Its not working. Here is my WebInterface code
package com.example.samosval;
import ...
class WebAppInterface{
Context mContext;
private DomainLoadStoreParameter resources;
/** Instantiate the interface and set the context */
WebAppInterface(Context c) {
mContext = c;
}
@JavascriptInterface
public void setItemVisible(String name) {
try {
NavigationView navigationView = (NavigationView) ((Activity) mContext).findViewById(R.id.nav_view);
MenuItem menuItem = navigationView.getMenu().findItem(getResId(name, R.id.class));
menuItem.setVisible(true);
} catch (Exception e) {
Log.e("TAGIF", "setItemVisible: ", e);
}
}
public static int getResId(String resName, Class<?> c) {
try {
Field idField = c.getDeclaredField(resName);
return idField.getInt(idField);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
}
But there is such an error
12-17 21:07:58.406 2229-2386/com.arystankaliakparov.samosval E/TAGIF: setItemVisible:
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:7234)
at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:1070)
at android.view.View.requestLayout(View.java:17932)
at android.view.View.requestLayout(View.java:17932)
at android.view.View.requestLayout(View.java:17932)
at android.view.View.requestLayout(View.java:17932)
at android.view.View.requestLayout(View.java:17932)
at android.view.View.requestLayout(View.java:17932)
at android.support.v4.widget.DrawerLayout.requestLayout(DrawerLayout.java:1303)
at android.view.View.requestLayout(View.java:17932)
at android.view.View.requestLayout(View.java:17932)
at android.support.v7.widget.RecyclerView.requestLayout(RecyclerView.java:4202)
at android.support.v7.widget.RecyclerView$RecyclerViewDataObserver.onChanged(RecyclerView.java:5286)
at android.support.v7.widget.RecyclerView$AdapterDataObservable.notifyChanged(RecyclerView.java:11997)
at android.support.v7.widget.RecyclerView$Adapter.notifyDataSetChanged(RecyclerView.java:7070)
at android.support.design.internal.NavigationMenuPresenter$NavigationMenuAdapter.update(NavigationMenuPresenter.java:474)
at android.support.design.internal.NavigationMenuPresenter.updateMenuView(NavigationMenuPresenter.java:114)
at android.support.v7.view.menu.MenuBuilder.dispatchPresenterUpdate(MenuBuilder.java:298)
at android.support.v7.view.menu.MenuBuilder.onItemsChanged(MenuBuilder.java:1069)
at android.support.v7.view.menu.MenuBuilder.onItemVisibleChanged(MenuBuilder.java:1108)
at android.support.v7.view.menu.MenuItemImpl.setVisible(MenuItemImpl.java:665)
at com.arystankaliakparov.samosval.WebAppInterface.setItemVisible(WebAppInterface.java:46)
at org.chromium.base.SystemMessageHandler.nativeDoRunLoopOnce(Native Method)
at org.chromium.base.SystemMessageHandler.handleMessage(SystemMessageHandler.java:53)
at android.os.Handler.dispatchMessage(Handler.java:111)
at android.os.Looper.loop(Looper.java:194)
at android.os.HandlerThread.run(HandlerThread.java:61)
Solution
You need to update the UI from the main thread. Use the runOnUiThread and you can update it.
runOnUiThread(new Runnable() {
@Override
public void run() {
// Update UI
}
});
Activity.runOnUiThread Documentation
Nest this inside of the method, then put the original code inside of the run function. Include only the smallest amount of code possible, otherwise you start to defeat the purpose of the background thread.
Answered By - Jay Mason
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.