DirectoryLoader.java revision 954be0232655d316bc5decbbd35579af902c75c2
1/* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package com.android.documentsui; 18 19import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME; 20import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED; 21import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE; 22 23import android.content.AsyncTaskLoader; 24import android.content.ContentProviderClient; 25import android.content.Context; 26import android.database.Cursor; 27import android.net.Uri; 28import android.os.CancellationSignal; 29import android.os.OperationCanceledException; 30import android.provider.DocumentsContract.Document; 31 32import libcore.io.IoUtils; 33 34class DirectoryResult implements AutoCloseable { 35 ContentProviderClient client; 36 Cursor cursor; 37 Exception exception; 38 39 @Override 40 public void close() { 41 IoUtils.closeQuietly(cursor); 42 ContentProviderClient.closeQuietly(client); 43 cursor = null; 44 client = null; 45 } 46} 47 48public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> { 49 private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver(); 50 51 private final String mRootId; 52 private final Uri mUri; 53 private final int mSortOrder; 54 55 private CancellationSignal mSignal; 56 private DirectoryResult mResult; 57 58 public DirectoryLoader(Context context, String rootId, Uri uri, int sortOrder) { 59 super(context); 60 mRootId = rootId; 61 mUri = uri; 62 mSortOrder = sortOrder; 63 } 64 65 @Override 66 public final DirectoryResult loadInBackground() { 67 synchronized (this) { 68 if (isLoadInBackgroundCanceled()) { 69 throw new OperationCanceledException(); 70 } 71 mSignal = new CancellationSignal(); 72 } 73 final DirectoryResult result = new DirectoryResult(); 74 final String authority = mUri.getAuthority(); 75 try { 76 result.client = getContext() 77 .getContentResolver().acquireUnstableContentProviderClient(authority); 78 final Cursor cursor = result.client.query( 79 mUri, null, null, null, getQuerySortOrder(mSortOrder), mSignal); 80 cursor.registerContentObserver(mObserver); 81 82 final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1); 83 final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder); 84 85 result.cursor = sorted; 86 } catch (Exception e) { 87 result.exception = e; 88 ContentProviderClient.closeQuietly(result.client); 89 } finally { 90 synchronized (this) { 91 mSignal = null; 92 } 93 } 94 return result; 95 } 96 97 @Override 98 public void cancelLoadInBackground() { 99 super.cancelLoadInBackground(); 100 101 synchronized (this) { 102 if (mSignal != null) { 103 mSignal.cancel(); 104 } 105 } 106 } 107 108 @Override 109 public void deliverResult(DirectoryResult result) { 110 if (isReset()) { 111 IoUtils.closeQuietly(result); 112 return; 113 } 114 DirectoryResult oldResult = mResult; 115 mResult = result; 116 117 if (isStarted()) { 118 super.deliverResult(result); 119 } 120 121 if (oldResult != null && oldResult != result) { 122 IoUtils.closeQuietly(oldResult); 123 } 124 } 125 126 @Override 127 protected void onStartLoading() { 128 if (mResult != null) { 129 deliverResult(mResult); 130 } 131 if (takeContentChanged() || mResult == null) { 132 forceLoad(); 133 } 134 } 135 136 @Override 137 protected void onStopLoading() { 138 cancelLoad(); 139 } 140 141 @Override 142 public void onCanceled(DirectoryResult result) { 143 IoUtils.closeQuietly(result); 144 } 145 146 @Override 147 protected void onReset() { 148 super.onReset(); 149 150 // Ensure the loader is stopped 151 onStopLoading(); 152 153 IoUtils.closeQuietly(mResult); 154 mResult = null; 155 156 getContext().getContentResolver().unregisterContentObserver(mObserver); 157 } 158 159 public static String getQuerySortOrder(int sortOrder) { 160 switch (sortOrder) { 161 case SORT_ORDER_DISPLAY_NAME: 162 return Document.COLUMN_DISPLAY_NAME + " ASC"; 163 case SORT_ORDER_LAST_MODIFIED: 164 return Document.COLUMN_LAST_MODIFIED + " DESC"; 165 case SORT_ORDER_SIZE: 166 return Document.COLUMN_SIZE + " DESC"; 167 default: 168 return null; 169 } 170 } 171} 172