DirectoryLoader.java revision 251097b3789632000ccdaf7fb7d66a82ff37d882
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 final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1); 81 final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder); 82 83 result.cursor = sorted; 84 result.cursor.registerContentObserver(mObserver); 85 } catch (Exception e) { 86 result.exception = e; 87 ContentProviderClient.closeQuietly(result.client); 88 } finally { 89 synchronized (this) { 90 mSignal = null; 91 } 92 } 93 return result; 94 } 95 96 @Override 97 public void cancelLoadInBackground() { 98 super.cancelLoadInBackground(); 99 100 synchronized (this) { 101 if (mSignal != null) { 102 mSignal.cancel(); 103 } 104 } 105 } 106 107 @Override 108 public void deliverResult(DirectoryResult result) { 109 if (isReset()) { 110 IoUtils.closeQuietly(result); 111 return; 112 } 113 DirectoryResult oldResult = mResult; 114 mResult = result; 115 116 if (isStarted()) { 117 super.deliverResult(result); 118 } 119 120 if (oldResult != null && oldResult != result) { 121 IoUtils.closeQuietly(oldResult); 122 } 123 } 124 125 @Override 126 protected void onStartLoading() { 127 if (mResult != null) { 128 deliverResult(mResult); 129 } 130 if (takeContentChanged() || mResult == null) { 131 forceLoad(); 132 } 133 } 134 135 @Override 136 protected void onStopLoading() { 137 cancelLoad(); 138 } 139 140 @Override 141 public void onCanceled(DirectoryResult result) { 142 IoUtils.closeQuietly(result); 143 } 144 145 @Override 146 protected void onReset() { 147 super.onReset(); 148 149 // Ensure the loader is stopped 150 onStopLoading(); 151 152 IoUtils.closeQuietly(mResult); 153 mResult = null; 154 155 getContext().getContentResolver().unregisterContentObserver(mObserver); 156 } 157 158 public static String getQuerySortOrder(int sortOrder) { 159 switch (sortOrder) { 160 case SORT_ORDER_DISPLAY_NAME: 161 return Document.COLUMN_DISPLAY_NAME + " ASC"; 162 case SORT_ORDER_LAST_MODIFIED: 163 return Document.COLUMN_LAST_MODIFIED + " DESC"; 164 case SORT_ORDER_SIZE: 165 return Document.COLUMN_SIZE + " DESC"; 166 default: 167 return null; 168 } 169 } 170} 171