কন্ট্রোলপ্রাইডার ছাড়া কার্সরলডার ব্যবহার usage


107

অ্যান্ড্রয়েড এসডিকে ডকুমেন্টেশন বলছে যে startManagingCursor()পদ্ধতিটি হ'ল:

এই পদ্ধতিটি হ্রাস করা হয়। পরিবর্তে লোডারম্যানেজারের সাথে নতুন কার্সরলডার শ্রেণিটি ব্যবহার করুন; এটি অ্যান্ড্রয়েড সামঞ্জস্যতা প্যাকেজের মাধ্যমে পুরানো প্ল্যাটফর্মগুলিতে উপলব্ধ। এই পদ্ধতিটি ক্রিয়াকলাপের জীবনচক্রের উপর ভিত্তি করে আপনার জন্য প্রদত্ত কার্সরের জীবনচক্রটি পরিচালনা করার জন্য ক্রিয়াকলাপটি যত্ন নিতে দেয়। এটি হ'ল, যখন ক্রিয়াকলাপ বন্ধ হয়ে যায় তা প্রদত্ত কার্সারে স্বয়ংক্রিয়ভাবে নিষ্ক্রিয় () ডেকে আনবে এবং পরে যখন এটি পুনরায় চালু হবে তখন এটি আপনার জন্য প্রয়োজনীয় () কল করবে। ক্রিয়াকলাপটি ধ্বংস হয়ে গেলে, সমস্ত পরিচালিত কার্সার স্বয়ংক্রিয়ভাবে বন্ধ হয়ে যাবে। আপনি যদি HONEYCOMB বা তারপরে টার্গেট করে থাকেন তবে পরিবর্তে LoaderManager ব্যবহার করে বিবেচনা করুন, getLoaderManager () এর মাধ্যমে উপলব্ধ

তাই আমি ব্যবহার করতে চাই CursorLoader। তবে যখন আমি কন্সট্রাক্টরের ইউআরআই লাগব তখন আমি কীভাবে এটি কাস্টম CursorAdapterএবং ছাড়াই ব্যবহার করতে পারি ?ContentProviderCursorLoader


@Alex লকউড কেন আমরা ContentProvider ছাড়া CursorAdapter ব্যবহার করছেন আমাকে সুপারিশ দয়া stackoverflow.com/questions/20419278/...

কেন আমরা ContentProvider ছাড়া CursorAdapter ব্যবহার করছেন আমাকে সুপারিশ দয়া stackoverflow.com/questions/20419278/...

উত্তর:


155

আমি একটি সাধারণ কার্সরলডার লিখেছি যাতে কোনও সামগ্রীর সরবরাহকারীর প্রয়োজন নেই:

import android.content.Context;
import android.database.Cursor;
import android.support.v4.content.AsyncTaskLoader;

/**
 * Used to write apps that run on platforms prior to Android 3.0. When running
 * on Android 3.0 or above, this implementation is still used; it does not try
 * to switch to the framework's implementation. See the framework SDK
 * documentation for a class overview.
 *
 * This was based on the CursorLoader class
 */
public abstract class SimpleCursorLoader extends AsyncTaskLoader<Cursor> {
    private Cursor mCursor;

    public SimpleCursorLoader(Context context) {
        super(context);
    }

    /* Runs on a worker thread */
    @Override
    public abstract Cursor loadInBackground();

    /* 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();
        }
    }

    /**
     * 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.
     * <p/>
     * 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;
    }
}

এটি শুধুমাত্র AsyncTaskLoaderক্লাস প্রয়োজন। অ্যানড্রয়েড 3.0.০ বা তার চেয়ে বেশি এর একটি বা সামঞ্জস্যতা প্যাকেজের সাথে আসে।

আমি এমন একটিও লিখেছিলামListLoader যা এর সাথে সামঞ্জস্যপূর্ণ LoadManagerএবং জেনেরিক java.util.Listসংগ্রহ পুনরুদ্ধার করতে ব্যবহৃত হয় ।


13
একটি দুর্দান্ত কোড উদাহরণ পাওয়া গেছে যা এটি ব্যবহার করে - বিটবুকিট.আর.সেসটি / ৪১৪৪৯66_মোবাইল অ্যাপ্লিকেশন / এসআরসি / এফসি ৫০70০ এএফএফডি / ডেমো / - - এটি খুব দরকারী বলে মনে হয়েছে!
শুশু

উদাহরণস্বরূপ ক্রিস্টিয়ান ধন্যবাদ। আপনার শ্রেণীর সাথে লাইসেন্সটি কী যুক্ত। কীভাবে এটি পুনরায় ব্যবহার করা যায়?
কোডগুজার

2
লাইসেন্স অ্যাপাচি ২.০; আপনি যেখানে / কখন চাইবেন এটি পুনরায় ব্যবহার করতে পারেন। আপনার কোনও উন্নতি হলে আমাকে জানান।
ক্রিশ্চিয়ান

14
দুর্দান্ত জিনিস! ব্যবহারকারীদের একটি সীমাবদ্ধতা সম্পর্কে সচেতন হওয়া উচিত, এটি হ'ল ডেটা পরিবর্তনের বিষয়ে রিফ্রেশ করার কোনও ব্যবস্থা নেই (লোডারদের যেমন করা উচিত)
এএমবি

1
এখানে @Jadeye আপনি মানুষ আছে: ListLoader এবং SupportListLoader
ক্রিস্টিয়ান

23

আপনার নিজস্ব লোডার লিখুন যা কোনও সামগ্রী সরবরাহকারীর পরিবর্তে আপনার ডাটাবেস ক্লাস ব্যবহার করে। সবচেয়ে সহজ উপায় হ'ল CursorLoaderসামঞ্জস্যতা গ্রন্থাগার থেকে শ্রেণীর উত্স নেওয়া , এবং সরবরাহকারীর অনুসন্ধানগুলি আপনার নিজের ডিবি সহায়ক শ্রেণীর কাছে প্রশ্নের সাথে প্রতিস্থাপন করা।


1
এটি আমার মতে সবচেয়ে সহজ উপায়। আমার অ্যাপ্লিকেশনটিতে আমি একটি CursorLoaderএসকিউএল কার্সার পরিচালনা করার জন্য একটি বংশধর তৈরি করেছি , কনস্ট্রাক্টরের কাছ থেকে আমার অ্যাপ্লিকেশনটি কেবলমাত্র loadInBackgroundআমার কার্সার ক্যোয়ারীর সাথে সরবরাহকারীর ক্যোয়ারীটি প্রতিস্থাপনের পদ্ধতিটি ওভাররাইড করতে হবে
জোসে_জিডি

14

সিম্পলসার্সরলডার একটি সহজ সমাধান, তবে ডেটা পরিবর্তন হওয়ার সাথে সাথে এটি লোডার আপডেট করার পক্ষে সমর্থন করে না। কমন্সওয়েরে একটি লোডেরেক্স গ্রন্থাগার রয়েছে যা একটি এসকিউএলাইটকার্সারলডার যুক্ত করে এবং ডেটা পরিবর্তনের বিষয়ে পুনরায় জিজ্ঞাসা সমর্থন করে।

https://github.com/commonsguy/cwac-loaderex


2
তবে, স্বয়ংক্রিয় পুনঃ-অনুসন্ধানের ব্যবহার করার জন্য, আপনাকে পশ্চাদপট পরিষেবাদির জন্য এর ব্যবহারযোগ্যতা সীমাবদ্ধ করে, ইউআই এবং আপডেটের জন্য একই লোডার ব্যবহার করতে হবে।
ge0rg

12

তৃতীয় বিকল্পটি কেবল ওভাররাইড করা হবে loadInBackground:

public class CustomCursorLoader extends CursorLoader {
    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    @Override
    public Cursor loadInBackground() {
        Cursor cursor = ... // get your cursor from wherever you like

        if (cursor != null) {
            // Ensure the cursor window is filled
            cursor.getCount();
            cursor.registerContentObserver(mObserver);
        }

        return cursor;
    }
};

এটি ডাটাবেস পরিবর্তিত হলে আপনার কার্সারটিকে পুনরায় জিজ্ঞাসা করার বিষয়েও যত্ন নেবে।

কেবলমাত্র সতর্কতামূলক: আপনাকে অন্য একজন পর্যবেক্ষককে সংজ্ঞায়িত করতে হবে, যেহেতু এর অনন্ত জ্ঞানের মধ্যে গুগল তাদের প্যাকেজটি ব্যক্তিগত করার সিদ্ধান্ত নিয়েছে। আপনি যদি ক্লাসটি মূল প্যাকেজের (বা কমপ্যাট এক) হিসাবে একই প্যাকেজে রাখেন তবে আপনি প্রকৃত আসল পর্যবেক্ষককে ব্যবহার করতে পারেন। পর্যবেক্ষক একটি খুব লাইটওয়েট অবজেক্ট এবং অন্য কোথাও ব্যবহার করা হয় না, সুতরাং এটি খুব বেশি পার্থক্য করে না।


দ্রুত পরীক্ষায় আমার পর্যবেক্ষণটি হ'ল কেবলমাত্র কার্সারকে কোনও সামগ্রী সরবরাহকারীকে টার্গেট করা হলে নিবন্ধকারকন্টেন্টঅবার্সারটিকে কার্সারের বিরুদ্ধে ডাকা হবে। আপনি কি এটিকে নিশ্চিত / অস্বীকার করতে পারবেন?
নিক ক্যাম্পিয়ন

1
এটি অবিচ্ছিন্নভাবে কন্টেন্টপ্রোভাইডার হতে হবে না। তবে কার্সারটি একটি বিজ্ঞপ্তি uri (setNotificationsUri) এ নিবন্ধিত হওয়া দরকার, এবং তারপরে ContentResolver.notifyChange কল করে এটির (সাধারণত একটি কন্টেন্টপ্রাইডার, তবে কিছু হতে পারে) কাউকে জানাতে হবে।
টিমো ওহর

4
হ্যাঁ। আপনার কাস্টমলডার এর উপর loadInBackground() , কার্সার ফিরিয়ে দেওয়ার আগে বলুন cursor.setNotificationUri(getContext().getContentResolver(), uri);ইউরি ঠিক এলোমেলো স্ট্রিং থেকে পছন্দ করতে পারে Uri.parse("content://query_slot1")। দেখে মনে হচ্ছে এটি সত্যিই ইউরির উপস্থিতি আছে কিনা তা যত্নশীল নয়। আর একবার আমি ডিবিতে অপারেশন করেছি। বলুন getContentResolver().notifyChange(uri, null);কৌতুক করবেন। তারপরে আমি খুব কম সংখ্যক প্রশ্নের সাথে অ্যাপের জন্য একটি কনটেন্ট ফাইলটিতে কয়েকটি "ক্যোরি ইউরি স্লট" তৈরি করতে পারি। আমি রানটাইমে ডিবি রেকর্ড সন্নিবেশ করিয়ে পরীক্ষা করি এবং এটি কাজ বলে মনে হয় তবে আমি এখনও সন্দেহ করি এটি ভাল অনুশীলন অনয়েট। যেকোনো পরামর্শ?
ইয়েং

আমি @ ইয়ুংয়ের পরামর্শ নিয়ে এই পদ্ধতিটি ব্যবহার করছি এবং ডেটাবেস আপডেটে কার্সারের স্বয়ংক্রিয় পুনরায় লোড সহ সবকিছু কাজ করে।
ডেভিড এইচ

এটির কোনও অনিবন্ধকন্টেন্টঅবার্সারের দরকার নেই?
জিপি্যাক 10

2

টিমো ওহর প্রস্তাবিত তৃতীয় বিকল্পটি, ইয়েংয়ের মন্তব্যের সাথে একসাথে সহজ উত্তর দেয় (ওকামের রেজার)। নীচে আমার জন্য কাজ করে এমন একটি সম্পূর্ণ শ্রেণীর উদাহরণ দেওয়া আছে। এই শ্রেণিটি ব্যবহারের জন্য দুটি নিয়ম রয়েছে।

  1. এই বিমূর্ত শ্রেণি প্রসারিত করুন এবং getCursor () এবং getContentUri () পদ্ধতি প্রয়োগ করুন।
  2. অন্তর্নিহিত ডাটাবেস যে কোনও সময় পরিবর্তিত হবে (যেমন, একটি সন্নিবেশ বা মোছার পরে), কল করতে ভুলবেন না

    getContentResolver().notifyChange(myUri, null);

    যেখানে মাইআউরি হ'ল একই পদ্ধতিটি আপনার getContentUri () এর পদ্ধতি প্রয়োগ থেকে ফিরে এসেছে।

আমি যে ক্লাসটি ব্যবহার করেছিলাম তার কোড এখানে:

package com.example.project;

import android.content.Context;
import android.database.Cursor;
import android.content.CursorLoader;
import android.content.Loader;

public abstract class AbstractCustomCursorLoader extends CursorLoader
  {
    private final Loader.ForceLoadContentObserver mObserver = new Loader.ForceLoadContentObserver();

    public AbstractCustomCursorLoader(Context context)
      {
        super(context);
      }

    @Override
    public Cursor loadInBackground()
      {
        Cursor cursor = getCursor();

        if (cursor != null)
          {
            // Ensure the cursor window is filled
            cursor.getCount();
            cursor.registerContentObserver(mObserver);
          }

        cursor.setNotificationUri(getContext().getContentResolver(), getContentUri());
        return cursor;
      }

    protected abstract Cursor getCursor();
    protected abstract Uri getContentUri();
  }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.