Android: Prevent notfying Parent/Descendent uri's in ContentProvider while using CursorLoader? - uri

I have a CursorLoader that observes a directory with this URI:
uriDirectory = content://com.myapp.stocks/stocks
and another CursorLoader that observes an item with this URI:
uriItem = content://com.myapp.stocks/stocks/GOOG
When I update uriItem and call getContext().getContentResolver().notifyChange(uriItem , null); in my ContentProvider, how can I prevent it from notifying uriDirectory as well?
Thanks!
Edit: So my solution so far is just to have a boolean that is set to true when I notify a uriItem. Then when it notifies the parent, uriDirectory, it will see that the boolean is true and won't perform any operations. After, I set the boolean back to false.

You can write your own CursorLoader. The default cursor loaders register a content observer via Cursor.RegisterContentObserver(ContentObserver observer). Instead, we want to use registerContentObserver(Uri uri, boolean notifyForDescendants, ContentObserver observer).
I'm not sure if you are using the support library CursorLoader but for the greatest applicability, that's what I'm using.
The only changes from the stock android versions are in loadInBackground(). You should create an entire class instead of just extending android's and overriding loadInBackground because it protects you from future changes made to Android. Be advised that this will not use any notification url you set for the cursor in your ContentProvider unless you the device is KitKat or newer
Uri notificationUri;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
notificationUri = cursor.getNotificationUri();
} else {
notificationUri = mUri;
}
getContext().getContentResolver().registerContentObserver(
notificationUri != null ? notificationUri : mUri,
false, //don't notify for descendants
mObserver
);
Full class descendantChangeIgnoringCursorLoader.java:
package com.innomatixdata.busscan.utils;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.support.v4.content.AsyncTaskLoader;
import android.support.v4.content.ContentResolverCompat;
import android.support.v4.content.Loader;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
public class DescendantChangeIgnoringCursorLoader extends AsyncTaskLoader<Cursor> {
final Loader.ForceLoadContentObserver mObserver;
Uri mUri;
String[] mProjection;
String mSelection;
String[] mSelectionArgs;
String mSortOrder;
Cursor mCursor;
android.support.v4.os.CancellationSignal mCancellationSignal;
/* Runs on a worker thread */
#Override
public Cursor loadInBackground() {
synchronized (this) {
if (isLoadInBackgroundCanceled()) {
throw new android.support.v4.os.OperationCanceledException();
}
mCancellationSignal = new android.support.v4.os.CancellationSignal();
}
try {
Cursor cursor = ContentResolverCompat.query(getContext().getContentResolver(),
mUri, mProjection, mSelection, mSelectionArgs, mSortOrder,
mCancellationSignal);
if (cursor != null) {
try {
// Ensure the cursor window is filled.
cursor.getCount();
Uri notificationUri;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
notificationUri = cursor.getNotificationUri();
} else {
notificationUri = mUri;
}
getContext().getContentResolver().registerContentObserver(
notificationUri != null ? notificationUri : mUri,
false, //don't notify for descendants
mObserver
);
} catch (RuntimeException ex) {
cursor.close();
throw ex;
}
}
return cursor;
} finally {
synchronized (this) {
mCancellationSignal = null;
}
}
}
#Override
public void cancelLoadInBackground() {
super.cancelLoadInBackground();
synchronized (this) {
if (mCancellationSignal != null) {
mCancellationSignal.cancel();
}
}
}
/* Runs on the UI thread */
#Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
// An async query came in while the loader is stopped
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;
if (isStarted()) {
super.deliverResult(cursor);
}
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}
/**
* Creates an empty unspecified CursorLoader. You must follow this with
* calls to {#link #setUri(Uri)}, {#link #setSelection(String)}, etc
* to specify the query to perform.
*/
public DescendantChangeIgnoringCursorLoader(Context context) {
super(context);
mObserver = new Loader.ForceLoadContentObserver();
}
/**
* Creates a fully-specified CursorLoader. See {#link ContentResolver#query(Uri, String[],
* String, String[], String) ContentResolver.query()} for documentation on the meaning of the
* parameters. These will be passed as-is to that call.
*/
public DescendantChangeIgnoringCursorLoader(Context context, Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
super(context);
mObserver = new Loader.ForceLoadContentObserver();
mUri = uri;
mProjection = projection;
mSelection = selection;
mSelectionArgs = selectionArgs;
mSortOrder = sortOrder;
}
/**
* Starts an asynchronous load of the contacts list data. When the result is ready the callbacks
* will be called on the UI thread. If a previous load has been completed and is still valid
* the result may be passed to the callbacks immediately.
*
* Must be called from the UI thread
*/
#Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
#Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
public Uri getUri() {
return mUri;
}
public void setUri(Uri uri) {
mUri = uri;
}
public String[] getProjection() {
return mProjection;
}
public void setProjection(String[] projection) {
mProjection = projection;
}
public String getSelection() {
return mSelection;
}
public void setSelection(String selection) {
mSelection = selection;
}
public String[] getSelectionArgs() {
return mSelectionArgs;
}
public void setSelectionArgs(String[] selectionArgs) {
mSelectionArgs = selectionArgs;
}
public String getSortOrder() {
return mSortOrder;
}
public void setSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
#Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
writer.print(prefix); writer.print("mUri="); writer.println(mUri);
writer.print(prefix); writer.print("mProjection=");
writer.println(Arrays.toString(mProjection));
writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
writer.print(prefix); writer.print("mSelectionArgs=");
writer.println(Arrays.toString(mSelectionArgs));
writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
}
}

Related

Using data-sly-use.object results in hiding the component

I am trying to recreate the Byline component activity in AEM WKND (https://experienceleague.adobe.com/docs/experience-manager-learn/getting-started-wknd-tutorial-develop/project-archetype/custom-component.html?lang=en#byline-styles). However when I tried to implement the html file, byline component is hidden in the page whenever I call data-sly-use api. Is there any workaround or solution for this one?
Below is my impl code:
#Model(adaptables = {SlingHttpServletRequest.class},
adapters = {Byline.class},
resourceType = {BylineImpl.RESOURCE_TYPE},
defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL)
public class BylineImpl implements Byline {
protected static final String RESOURCE_TYPE = "wknd/components/byline";
#Self
private SlingHttpServletRequest request;
#OSGiService
private ModelFactory modelFactory;
#ValueMapValue
private String name;
#ValueMapValue
private List<String> occupations;
private Image image;
#Override
public String getName() {
return name;
}
#PostConstruct
private void init(){
image = modelFactory.getModelFromWrappedRequest(request, request.getResource(), Image.class);
}
#Override
public List<String> getOccupations() {
if (occupations != null) {
Collections.sort(occupations);
return new ArrayList<String>(occupations);
} else {
return Collections.emptyList();
}
}
#Override
public boolean isEmpty() {
final Image componentImage = getImage();
if (StringUtils.isBlank(name)) {
// Name is missing, but required
return true;
} else if (occupations == null || occupations.isEmpty()) {
// At least one occupation is required
return true;
} else if (componentImage == null || StringUtils.isBlank(componentImage.getSrc())) {
// A valid image is required
return true;
} else {
// Everything is populated, so this component is not considered empty
return false;
}
}
private Image getImage() {
return image;
}
}
Below is my byline.html code:
div data-sly-use.byline="com.adobe.aem.guides.wknd.core.models.impl.BylineImpl"
data-sly-use.placeholderTemplate="core/wcm/components/commons/v1/templates.html"
data-sly-test.hasContent="${!byline.empty}" class="cmp-byline">
<div class="cmp-byline__image" data-sly-resource="${ '.' # resourceType = 'core/wcm/components/image/v2/image' }">
</div>
<h2 class="cmp-byline__name">${byline.name}</h2>
<p class="cmp-byline__occupations">${byline.occupations # join=', '}</p>
</div>
<sly data-sly-call="${placeholderTemplate.placeholder # isEmpty=!hasContent}"></sly>

Dependency service and mediaPlayer

i am using dependency service to use Android MediaPlayer, however once i return the value from media player to shared project the value mediaplayer is null. I have seen and tried https://github.com/xamarin/xamarin-forms-samples/blob/master/UserInterface/MediaElementDemos/MediaElementDemos.Android/VideoPicker.cs
My interface
public interface IDictionaryPlayer
{
MediaPlayer SetGong(int timeoutBetweenWords);
}
Droid
public MediaPlayer SetGong(int timeout)
{
MediaPlayer pausesPlayer = MediaPlayer.Create(Android.App.Application.Context, Resource.Raw.gong);
return pausesPlayer;
}
Shared project
public static MediaPlayer GongPlayer;
public static void SetPauseOrGongBetweenWords(int timeoutBetweenWords)
{
GongPlayer = DependencyService.Get<IDictionaryPlayer>().SetGong(timeoutBetweenWords); // HERE ITS NULL
initialize = true;
GongPlayer.Start();
}
public static void TryPausePlayer()
{
lock (playerLock)
{
if (GongPlayer != null && GongPlayer.IsPlaying)
{
gongNeedsResume = true;
GongPlayer?.Pause();
}
}
}
public static void TryResumePlayer()
{
if (gongNeedsResume)
{
gongNeedsResume = false;
GongPlayer?.Start();
}
}
internal static void Clean()
{
disposeActive = true;
if (GongPlayer != null)
{
GongPlayer.Dispose();
GongPlayer = null;
}
}

onRequestPermissionsResult() does not finish before onViewCreated() conduct

public class PdfRendererBasicFragment extends Fragment implements View.OnClickListener {
/**
* Key string for saving the state of current page index.
*/
private static final String STATE_CURRENT_PAGE_INDEX = "current_page_index";
public static final int EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE = 2;
/**
* File descriptor of the PDF.
*/
/**
* {#link android.graphics.pdf.PdfRenderer} to render the PDF.
*/
private PdfRenderer mPdfRenderer;
/**
* Page that is currently shown on the screen.
*/
private PdfRenderer.Page mCurrentPage;
/**
* {#link android.widget.ImageView} that shows a PDF page as a {#link android.graphics.Bitmap}
*/
private ImageView mImageView;
/**
* {#link android.widget.Button} to move to the previous page.
*/
private Button mButtonPrevious;
/**
* {#link android.widget.Button} to move to the next page.
*/
private Button mButtonNext;
private Bundle copySavedInstanceState;
public PdfRendererBasicFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_pdf_renderer_basic, container, false);
}
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Retain view references.
mImageView = (ImageView) view.findViewById(R.id.image);
mButtonPrevious = (Button) view.findViewById(R.id.previous);
mButtonNext = (Button) view.findViewById(R.id.next);
// Bind events.
mButtonPrevious.setOnClickListener(this);
mButtonNext.setOnClickListener(this);
mImageView.setOnClickListener(this);
copySavedInstanceState = savedInstanceState;
while (true) {
int rc = ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (rc == PackageManager.PERMISSION_GRANTED)
break;
}
// Show the first page by default.
int index = 0;
// If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
if (null != copySavedInstanceState) {
index = copySavedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);
}
Log.d("check","index : " + index);
showPage(index);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
int rc = ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (rc == PackageManager.PERMISSION_GRANTED) {
try {
openRenderer(activity);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(activity, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
activity.finish();
}
} else {
requestExternalStoragePermission();
}
}
#Override
public void onDetach() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onDetach();
}
#Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
if (null != mCurrentPage) {
outState.putInt(STATE_CURRENT_PAGE_INDEX, mCurrentPage.getIndex());
}
}
private void requestExternalStoragePermission() {
final String[] permissions = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
if (!ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
ActivityCompat.requestPermissions(getActivity(), permissions, EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
return;
}
final Activity thisActivity = getActivity();
View.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View view) {
ActivityCompat.requestPermissions(thisActivity, permissions,
EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE);
}
};
}
#Override
public void onRequestPermissionsResult(int requestCode,
#NonNull String[] permissions,
#NonNull int[] grantResults) {
if (requestCode != EXTERNAL_STORAGE_PERMISSION_REQUEST_CODE) {
Log.d("TAG", "Got unexpected permission result: " + requestCode);
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
return;
}
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
Log.d("TAG", "Camera permission granted - initialize the camera source");
// we have permission, so can read SD Card now.
try {
openRenderer(getActivity());
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
getActivity().finish();
}
return;
}
Log.e("TAG", "Permission not granted: results len = " + grantResults.length +
" Result code = " + (grantResults.length > 0 ? grantResults[0] : "(empty)"));
DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
}
};
}
/**
* Sets up a {#link android.graphics.pdf.PdfRenderer} and related resources.
*/
private void openRenderer(Context context) throws IOException {
File file = new File("/sdcard/Download/test.pdf");
mPdfRenderer = new PdfRenderer(ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY));
}
/**
* Closes the {#link android.graphics.pdf.PdfRenderer} and related resources.
*
* #throws java.io.IOException When the PDF file cannot be closed.
*/
private void closeRenderer() throws IOException {
if (null != mCurrentPage) {
mCurrentPage.close();
}
mPdfRenderer.close();
}
/**
* Shows the specified page of PDF to the screen.
*
* #param index The page index.
*/
private void showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return;
}
// Make sure to close the current page before opening another one.
if (null != mCurrentPage) {
mCurrentPage.close();
}
// Use `openPage` to open a specific page in PDF.
mCurrentPage = mPdfRenderer.openPage(index);
// Important: the destination bitmap must be ARGB (not RGB).
Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
Bitmap.Config.ARGB_8888);
// Here, we render the page onto the Bitmap.
// To render a portion of the page, use the second and third parameter. Pass nulls to get
// the default result.
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// We are ready to show the Bitmap to user.
mImageView.setImageBitmap(bitmap);
updateUi();
}
/**
* Updates the state of 2 control buttons in response to the current page index.
*/
private void updateUi() {
int index = mCurrentPage.getIndex();
int pageCount = mPdfRenderer.getPageCount();
mButtonPrevious.setEnabled(0 != index);
mButtonNext.setEnabled(index + 1 < pageCount);
getActivity().setTitle(getString(R.string.app_name_with_index, index + 1, pageCount));
}
/**
* Gets the number of pages in the PDF. This method is marked as public for testing.
*
* #return The number of pages.
*/
public int getPageCount() {
return mPdfRenderer.getPageCount();
}
#Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.previous: {
// Move to the previous page
showPage(mCurrentPage.getIndex() - 1);
break;
}
case R.id.next: {
// Move to the next page
Log.d("name", mCurrentPage.getIndex() + "");
showPage(mCurrentPage.getIndex() + 1);
break;
}
case R.id.image: {
Log.d("name", mCurrentPage.getIndex() + "");
break;
}
}
}
}
HI, this is my code.
I try to fix. but it's not going well.
problem is this.
When I conduct this app. Android request permission, and I Approve.
but at that time android perform 'onViewCreated(View view, Bundle savedInstanceState)' method before 'openRenderer(activity)' is done.
so 'showPage(index)' raise some error. and after then (I mean permission already approved, and execute again) app doing well.
but I want to fix that.
I think
At the first time, onAttach(Activity activity) execute
and after permission approved,
onAttach(Activity activity) and
onViewCreated(View view, Bundle savedInstanceState)
methods seems to run at the same time.
Please advice me.
Thank you.
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
// Retain view references.
Log.d("timeStamp", "onViewCreated ");
mImageView = (ImageView) view.findViewById(R.id.image);
mButtonPrevious = (Button) view.findViewById(R.id.previous);
mButtonNext = (Button) view.findViewById(R.id.next);
// Bind events.
mButtonPrevious.setOnClickListener(this);
mButtonNext.setOnClickListener(this);
mImageView.setOnClickListener(this);
Log.d("timeStamp", "onViewCreated 할당완료");
while (true) {
int rc = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (rc == PackageManager.PERMISSION_GRANTED){
try {
openRenderer(getActivity());
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
getActivity().finish();
}
break;
}
Log.d("timeStamp", "얼마나 기다리는겨");
}
// Show the first page by default.
int index = 0;
// If there is a savedInstanceState (screen orientations, etc.), we restore the page index.
if (null != savedInstanceState) {
index = savedInstanceState.getInt(STATE_CURRENT_PAGE_INDEX, 0);
}
Log.d("timeStamp", "showPage 호출 직전");
showPage(index);
}
}
I avoid this problem to add this code.
while (true) {
int rc = getActivity().checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE);
if (rc == PackageManager.PERMISSION_GRANTED){
try {
openRenderer(getActivity());
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(getActivity(), "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
getActivity().finish();
}
break;
}
Log.d("timeStamp", "얼마나 기다리는겨");
}
but. this is not a best.
I figured this happen because onAttach method call requestPermissions method and end. onViewCreated start before User answer to request and onRequestPermissionsResult called (So openRenderer start).
So I suspend showPage method until PERMISSION_GRANTED.

JSF custom panel with button - action not invoked

I have built a custom component button, but somehow the action is not invoked. When debugging the getAction-Method within the component and invoking the supplied MethodeExpression the Bean-Method is called as expected. But due to some reason, the Expression is not invoked when pressing the button in the browser.
Is there some kind of additional Interface necessary to pass the action to the embedded button-component?
Any help is very appreciated since I am stuck at this issue for some days now
MyClass:
public class MyClass extends UIPanel implements SystemEventListener
{
private UIForm form;
private HtmlCommandButton buttonOk;
public MyClass()
{
FacesContext context = getFacesContext();
UIViewRoot root = context.getViewRoot();
root.subscribeToViewEvent(PostAddToViewEvent.class, this);
}
#Override
public void processEvent(SystemEvent event)
{
this.form = new UIForm();
this.buttonOk = new HtmlCommandButton();
this.buttonOk.setId("okButtonId");
this.buttonOk.setActionExpression(getAction());
this.buttonOk.setValue("OK");
this.form.getChildren().add(this.buttonOk);
getChildren().add(this.form);
}
private enum PropertyKeys
{
action, text, titel
}
public MethodExpression getAction()
{
return (MethodExpression) getStateHelper().eval(PropertyKeys.action);
}
public void setAction(MethodExpression actionExpression)
{
getStateHelper().put(PropertyKeys.action, actionExpression);
}
public String getText()
{
return (String) getStateHelper().eval(PropertyKeys.text);
}
public void setText(String text)
{
getStateHelper().put(PropertyKeys.text, text);
}
public String getTitel()
{
return (String) getStateHelper().eval(PropertyKeys.titel);
}
public void setTitel(String titel)
{
getStateHelper().put(PropertyKeys.titel, titel);
}
#Override
public void encodeAll(FacesContext context) throws IOException
{
ResponseWriter writer = context.getResponseWriter();
writer.startElement(HTML.DIV_ELEM, this);
writer.writeText(getText(), null);
this.form.encodeAll(context);
writer.endElement(HTML.DIV_ELEM);
}
#Override
public void encodeChildren(FacesContext context) throws IOException
{
}
#Override
public boolean isListenerForSource(Object source)
{
return (source instanceof MyClass);
}
}
MyClassHandler:
public class MyClassHandler extends ComponentHandler
{
public MyClassHandler(ComponentConfig config)
{
super(config);
}
#SuppressWarnings("rawtypes")
#Override
protected MetaRuleset createMetaRuleset(Class type)
{
return super.createMetaRuleset(type).addRule(new MethodRule("action", String.class, new Class[] { ActionEvent.class }));
}
}
myView Method:
...
public String myMethod()
{
System.err.println("myMethod");
return "/some/path/yadayada.xhtml";
}
...
MyView.xhtml
<myTag action="#{myView.myMethod}" id="id1" titel="bla" text="bleh" />
Exdending UICommand is enough, since you only want one action to be executed.
You have to provide two additional MethodExpressions via the tag-attributes and within the decode-method you can check which button has been pressed and redirect the particular MethodExpression to the standard-action provided by UICommand. This way, you dont have to worry about the legacy-interface ActionSource, or how Events are broadcasted.
public void decode(FacesContext contex)
{
Map<String,String> map = context.getExternalContext.getRequestParameterMap();
// your rendered buttons need a name you check for
final boolean okPressed = map.containsKey( getClientId + ":ok" );
final boolean cancelPressed = map.containsKey( getClientId + ":cancel" );
if(okPressed || cancelPressed)
{
MethodExpression exp = null;
if(okPressed)
{
exp = getActionOk();
}
else
{
exp = getActionCancel();
}
// redirect to standard action
setActionExpression(exp);
queueEvent(new ActionEvent(this));
}
}
In order to make use of of this you need two attributes (actionOk and actionCancel) which use Method Expressions (setter and getter). Those have to be configured by a ComponentHandler as you did for the action-attribute.

Android implement CursorLoader to SQLite database loader

I want to have two ListView in one Activity. I am trying to use Fragments. Data will loaded to ListViews from Sqlite database. I implement AsyncTaskLoader for working with SQllite used source code of cursorloader, but method doInBackground() issue mistake. This is my code:
public class DatabaseLoader extends AsyncTaskLoader<Cursor> {
final ForceLoadContentObserver mObserver;
SQLiteDatabase mDb;
String mTable;
String[] mColumns;
String mSelection;
String[] mSelectionArgs;
String mSortOrder;
Cursor mCursor;
/* Runs on a worker thread */
#Override
public Cursor loadInBackground() {
Cursor cursor = mDb.query(mTable, mColumns, mSelection,
mSelectionArgs, null, null, mSortOrder, null);
if (cursor != null) {
cursor.getCount();
registerContentObserver(cursor, mObserver);
}
return cursor;
}
void registerContentObserver(Cursor cursor, ContentObserver observer) {
cursor.registerContentObserver(mObserver);
}
/* Runs on the UI thread */
#Override
public void deliverResult(Cursor cursor) {
if (isReset()) {
// An async query came in while the loader is stopped
if (cursor != null) {
cursor.close();
}
return;
}
Cursor oldCursor = mCursor;
mCursor = cursor;
if (isStarted()) {
super.deliverResult(cursor);
}
if (oldCursor != null && oldCursor != cursor && !oldCursor.isClosed()) {
oldCursor.close();
}
}
public DatabaseLoader(Context context) {
super(context);
mObserver = new ForceLoadContentObserver();
}
public DatabaseLoader(Context context, String table, String[] columns, String selection,
String[] selectionArgs, String sortOrder) {
super(context);
mObserver = new ForceLoadContentObserver();
mTable = table;
mColumns = columns;
mSelection = selection;
mSelectionArgs = selectionArgs;
mSortOrder = sortOrder;
}
#Override
protected void onStartLoading() {
if (mCursor != null) {
deliverResult(mCursor);
}
if (takeContentChanged() || mCursor == null) {
forceLoad();
}
}
/**
* Must be called from the UI thread
*/
#Override
protected void onStopLoading() {
// Attempt to cancel the current load task if possible.
cancelLoad();
}
#Override
public void onCanceled(Cursor cursor) {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
#Override
protected void onReset() {
super.onReset();
// Ensure the loader is stopped
onStopLoading();
if (mCursor != null && !mCursor.isClosed()) {
mCursor.close();
}
mCursor = null;
}
public String getTable() {
return mTable;
}
public void setTable(String table) {
mTable = table;
}
public String[] getColumns() {
return mColumns;
}
public void setColumns(String[] columns) {
mColumns = columns;
}
public String getSelection() {
return mSelection;
}
public void setSelection(String selection) {
mSelection = selection;
}
public String[] getSelectionArgs() {
return mSelectionArgs;
}
public void setSelectionArgs(String[] selectionArgs) {
mSelectionArgs = selectionArgs;
}
public String getSortOrder() {
return mSortOrder;
}
public void setSortOrder(String sortOrder) {
mSortOrder = sortOrder;
}
#Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
super.dump(prefix, fd, writer, args);
// writer.print(prefix); writer.print("mUri="); writer.println(mUri);
writer.print(prefix); writer.print("mTable="); writer.println(mTable);
writer.print(prefix); writer.print("mColumns="); writer.println(Arrays.toString(mColumns));
writer.print(prefix); writer.print("mSelection="); writer.println(mSelection);
writer.print(prefix); writer.print("mSelectionArgs="); writer.println(Arrays.toString(mSelectionArgs));
writer.print(prefix); writer.print("mSortOrder="); writer.println(mSortOrder);
writer.print(prefix); writer.print("mCursor="); writer.println(mCursor);
// writer.print(prefix); writer.print("mContentChanged=");
writer.println(mContentChanged);
}
}
Can help me somebody. Why method doInBackground() don't work?
You have to open the Database mDb before performing query on it.

Resources