自定义支持加载器出现问题

时间:2012-03-09 03:15:31

标签: android

我设置使用Loader模式并且使用游标方法有问题,所以我重构了我的代码因为我的表不使用_id作为主键因为使用了关联表而我设置了我的代码使用与android开发人员站点中的LoaderCustomSupport.java示例相同的基本结构。所有代码都可以正常运行,我可以看到我有正确的数据并准备好显示ListFragment但在onLoadFinished回调完成后,适配器上的setData永远不会调用getView。我的getView看起来像这样:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    PhoneNumberListHolder holder;

    if (row == null) {
        row = mInflater.inflate(R.layout.phonenumber_row, parent, false);

        holder=new PhoneNumberListHolder(row);

        row.setTag(holder);
    } else {
        holder = (PhoneNumberListHolder)row.getTag(); 
    }

    holder.populateForm(this.phoneNumbers.get(position));
    return row;
}

我正在尝试使用持有者模式,但我想这可能是我的问题的一部分。我可能会出错的任何想法?

这是加载程序代码(就像我说的那样,我在第一次运行时遵循Google示例,改变了我认为我需要的内容)

我班级的抽象装载者

/*
* Custom version of CommonsWare, LLC, AbstractCursorLoader
*
*/
package myApp.service.data;

import java.util.List;
import android.content.Context;
import android.support.v4.content.AsyncTaskLoader;

abstract public class AbstractPhoneNumberLoader extends AsyncTaskLoader<List<PhoneNumber>> {
abstract protected List<PhoneNumber> buildPhoneNumber();
List<PhoneNumber> lastPhoneNumber=null;

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

@Override
public List<PhoneNumber> loadInBackground() {
    List<PhoneNumber> data=buildPhoneNumber();

    if (data!=null) {
        // Make sure we fill the person
        data.size();
    }
    return (data);
}

/**
 * This will run on the UI thread, routing the results from the 
 * background to the consumer of the Person object
 * (e.g., a PhoneNumberListAdapter).
 */
@Override
public void deliverResult(List<PhoneNumber> data) {
    if (isReset()) {
        // An async query attempted a call while the loader is stopped
        if (data!=null) {
            data.clear();
            data=null; 
            //not sure the best option here since we cannot close the List object
        }
        return;
    }

    List<PhoneNumber> oldPhoneNumber=lastPhoneNumber;
    lastPhoneNumber=data;

    if (isStarted()) {
        super.deliverResult(data);          
    }

    if (oldPhoneNumber!=null && oldPhoneNumber!=data && oldPhoneNumber.isEmpty()) {
        oldPhoneNumber.clear();
        oldPhoneNumber=null;
    }
}

/**
 * Start an asynchronous load of the requested data.
 * When the result is ready the callbacks will be called 
 * on the UI thread.  If a previous load has completed 
 * and is still valid the result may be passed back to the 
 * caller immediately.
 * 
 * Note: Must be called from the UI thread
 */
@Override
protected void onStartLoading() {
    if (lastPhoneNumber!=null) {
        deliverResult(lastPhoneNumber);
    }
    if (takeContentChanged() || lastPhoneNumber==null) {
        forceLoad();
    }
}

/**
 * Must be called from the UI thread, triggered by
 * a call to stopLoading().
 */
@Override
protected void onStopLoading() {
    // Attempt to cancel the current load task
    cancelLoad();
}

 /**
   * Must be called from the UI thread, triggered by a
   * call to cancel(). Here, we make sure our Person 
   * is null, if it still exists and is not already empty.
   */
  @Override
  public void onCanceled(List<PhoneNumber> data) {
    if (data!=null && !data.isEmpty()) {
      data.clear();
    }
  }

  /**
   * Must be called from the UI thread, triggered by a
   * call to reset(). Here, we make sure our Person
   * is empty, if it still exists and is not already empty.
   */
  @Override
  protected void onReset() {
    super.onReset();

    // Ensure the loader is stopped
    onStopLoading();

    if (lastPhoneNumber!=null && !lastPhoneNumber.isEmpty()) {
      lastPhoneNumber.clear();
    }

    lastPhoneNumber=null;
  }
}

数据加载器

/*
* Custom version of CommonsWare, LLC, SQLiteCursorLoader
*
*/
package myApp.service.data;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.List;
import myApp.service.data.ActorDbAdapter;
import android.content.Context;

public class PhoneNumberDataLoader extends AbstractPhoneNumberLoader {
ActorDbAdapter db=null;

protected final String actorId;
protected final String _PHONENUMBERID = "PhoneNumberId";

protected SimpleDateFormat dateFormat = new SimpleDateFormat("dd/mm/yyyy"); 

/**
 * Constructor - takes the context to allow the database to be
 * opened/created
 * 
 * @param ctx the Context within which to work
 */
public PhoneNumberDataLoader(Context ctx, String actorId) {
    super(ctx);
    this.actorId = actorId;
    getHelper(ctx);
}

// Get a database connection
private void getHelper(Context ctx) {  
    if (db==null) {
        db=new ActorDbAdapter(ctx);
    }
    db.open();
}
// Loader Methods
/**
 * Runs on a worker thread and performs the actual
 * database query to retrieve the PhoneNumber List.
 */
@Override
protected List<PhoneNumber> buildPhoneNumber() {
    return(db.readPhoneById(actorId));
}

/**
 * Writes a semi-user-readable roster of contents to
 * supplied output.
 */
@Override
public void dump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
    super.dump(prefix, fd, writer, args);
    writer.print(prefix);
    writer.print("actorId=");
    writer.println(actorId);
}

public void insert(PhoneNumber data, String actorId) {
    new InsertTask(this).execute(db, data, actorId);
}

// Saved for Later, get Reads and Writes working first
//  public void update(PhoneNumber data, String actorId, String whereClause, String[] whereArgs) {
//      new UpdateTask(this).execute(db, data, actorId, whereClause, whereArgs);
//  }
//
//  public void delete(String actorId, String phoneNumberId, String whereClause, String[] whereArgs) {
//      new DeleteTask(this).execute(db, actorId, phoneNumberId, whereClause, whereArgs);
//  }

public void execSQL(String actorId) {
    new ExecSQLTask(this).execute(db, actorId);
}

private class InsertTask extends ContentChangingTask<Object, Void, Void> {
    InsertTask(PhoneNumberDataLoader loader) {
        super(loader);
    }

    @Override
    protected Void doInBackground(Object... params) {
        ActorDbAdapter db=(ActorDbAdapter)params[0];
        PhoneNumber data=(PhoneNumber)params[1];
        int actorId=Integer.parseInt((String)params[2]);

        db.createPhoneNumber(data, actorId);

        return(null);
    }
}

// Saved for Later, get Reads and Writes working first
//  private class UpdateTask extends
//  ContentChangingTask<Object, Void, Void> {
//      UpdateTask(PhoneNumberDataLoader loader) {
//          super(loader);
//      }
//
//      @Override
//      protected Void doInBackground(Object... params) {
//          ActorDbAdapter db=(ActorDbAdapter)params[0];
//          String table=(String)params[1];
//          int actorId=Integer.parseInt((String)params[2]);
//          String where=(String)params[3];
//          String[] whereParams=(String[])params[4];
//
//          db.updatePhoneNumber(table, values, where, whereParams);
//
//          return(null);
//      }
//  }
//
//  private class DeleteTask extends
//  ContentChangingTask<Object, Void, Void> {
//      DeleteTask(PhoneNumberDataLoader loader) {
//          super(loader);
//      }
//
//      @Override
//      protected Void doInBackground(Object... params) {
//          ActorDbAdapter db=(ActorDbAdapter)params[0];
//          int actorId=Integer.parseInt((String)params[1]);
//          int phoneNumberId=Integer.parseInt((String)params[2]);
//          String where=(String)params[3];
//          String[] whereParams=(String[])params[3];
//
//          db.deletePhoneNumber(table, where, whereParams);
//
//          return(null);
//      }
//  }

private class ExecSQLTask extends
ContentChangingTask<Object, Void, Void> {
    ExecSQLTask(PhoneNumberDataLoader loader) {
        super(loader);
    }

    @Override
    protected Void doInBackground(Object... params) {
        ActorDbAdapter db=(ActorDbAdapter)params[0];
        String actorId=(String)params[1];

        db.readPhoneById(actorId);

        return(null);
    }
}
} 

这是我的完整ListAdapter

package myApp.planner.utilities;

import java.util.ArrayList;
import java.util.List;

import myApp.planner.R;
import myApp.planner.codes.PhoneOrAddressTypeCode;
import myApp.service.data.PhoneNumber;
import myApp.service.data.PhoneNumberListData;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.TextView;

public class PhoneNumberListAdapter extends ArrayAdapter<PhoneNumber> {
private List<PhoneNumber> phoneNumbers;
private final LayoutInflater mInflater;
private Activity activity;

public PhoneNumberListAdapter(Activity a, int textViewResourceId) {
    super(a, textViewResourceId);
    activity = a;
    mInflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
}

public void setData(List<PhoneNumber> data) {
    if (this.phoneNumbers==null) {
        this.phoneNumbers = new ArrayList<PhoneNumber>();
    }
    this.phoneNumbers.clear();
    if (data != null) {
        for (PhoneNumber phoneNumber : data) {
            this.phoneNumbers.add(phoneNumber);
        }  
    }
}

public static class PhoneNumberListHolder {
    private TextView actorid=null;
    private TextView phonenumberid=null;
    private TextView phonetype=null;
    private TextView phonenumber=null;
    private CheckBox isprimary=null;

    PhoneNumberListHolder(View row) {
        actorid=(TextView)row.findViewById(R.id.actorid);
        phonenumberid=(TextView)row.findViewById(R.id.phonenumberid);
        phonetype=(TextView)row.findViewById(R.id.txtphonetype);
        phonenumber=(TextView)row.findViewById(R.id.txtphonenumber);
        isprimary=(CheckBox)row.findViewById(R.id.isprimary);
    }

    //void populateForm(ArrayList<PhoneNumberListData> c, int position) { 
    void populateForm(PhoneNumber data) {   

        //PhoneNumberListData data = c.get(position);
        // Attempt to add the Actor ID
        if (actorid != null){
            actorid.setText(data.getActor().get(0).getActorId()==0 ? "0": Integer.toString(data.getActor().get(0).getActorId()));
        }

        // Attempt to add the Phone Number Item ID
        if (phonenumberid != null){
            phonenumberid.setText(data.getPhoneNumberId()==0 ? "0": Integer.toString(data.getPhoneNumberId()));
        }

        // Attempt to add the Phone Number Type
        if (phonetype != null){
            phonetype.setText(data.getPhoneType()==null ? "": PhoneOrAddressTypeCode.valueOf(data.getPhoneType()).toString());

        }

        // Attempt to add the Phone Number
        if (phonenumber != null){
            phonenumber.setText(data.getPhoneNumber1()==null ? "": data.getPhoneNumber1());
        }

        // Attempt to add the is Primary Flag
        if (isprimary != null){
            isprimary.setChecked(data.getIsPrimary()==0 ? Boolean.FALSE: Boolean.TRUE);
        }
    }
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View row = convertView;
    PhoneNumberListHolder holder;

    if (row == null) {
        row = mInflater.inflate(R.layout.phonenumber_row, parent, false);

        holder=new PhoneNumberListHolder(row);

        row.setTag(holder);
    } else {
        holder = (PhoneNumberListHolder)row.getTag(); 
    }

    holder.populateForm(this.phoneNumbers.get(position));
    return row;
}
}   

ListFragment

package myApp.planner;

import java.util.ArrayList;
import java.util.List;
import android.support.v4.app.ListFragment;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SearchViewCompat;
import android.support.v4.widget.SearchViewCompat.OnQueryTextListenerCompat;
import android.text.TextUtils;
import android.content.Intent;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.database.Cursor;
import android.view.ContextMenu;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ListView;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import myApp.planner.R;
import myApp.planner.utilities.PhoneNumberListAdapter;
import myApp.service.data.PhoneNumber;
import myApp.service.data.PhoneNumberDataLoader;

public class ActorPhoneNumberListFragment extends ListFragment implements LoaderManager.LoaderCallbacks<List<PhoneNumber>> {
public final static String ID_EXTRA="myapp.planner.actorid";
protected final static String TAG = "ActorPhoneNumberListFragment";
private static final int ADD_ID=Menu.FIRST + 1;
private static final int DELETE_ID=Menu.FIRST + 3;
private PhoneNumberListAdapter mAdapter=null;
private PhoneNumberDataLoader loader=null;
private String mCurFilter;
private String actorId = "0";
//private SharedPreferences prefs=null;
OnActorPhoneNumberListListener listener=null;
OnQueryTextListenerCompat mOnQueryTextListenerCompat;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    this.actorId = getActivity().getIntent().getExtras().getString(ID_EXTRA).toString();
}

@Override
public void onResume() {
    super.onResume();

    Bundle args=getArguments();

    if (args!=null) {
        loadPhoneNumbers(args.getString(ID_EXTRA));
    }
    // init Empty Test for no Phone numbers Found

    // Add the menu options that we need to manage the list
    setHasOptionsMenu(true);

    // Hookup the dbAdapter and create a blank adapter
    initList();
}

@Override
public void onPause() {
    super.onPause();
}

@Override
public void onListItemClick(ListView list, View view, int position, long id) {
    if (listener!=null) {
        //We will actually want the PhoneNumber Id here for the popup edit screen
        String mId = actorId;
        listener.onActorPhoneNumberListSelected(mId);
    }
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.phonenumber_opton, menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId()==R.id.addNewPhone) {
        //add();
        return(true);
    } else if (item.getItemId()==R.id.help) {
        startActivity(new Intent(getActivity(), HelpPage.class));
        return(true);
    } else if (item.getItemId()==R.id.phoneRefresh) {
        //startActivity(new Intent(getActivity(), ActorPhoneNumberListFragment.class));
        //We may just need to refresh the loader
        return(true);
} else 
    return(super.onOptionsItemSelected(item));
}

public void setOnActorPhoneNumberListListener(OnActorPhoneNumberListListener listener) {
    this.listener=listener;
}

public void loadPhoneNumbers(String actorId) {
    this.actorId=actorId;
}

private void initList() {
    mAdapter=new PhoneNumberListAdapter(getActivity(), R.layout.phonenumber_row);
    setListAdapter(mAdapter);

    // Start out with a progress indicator.
    setListShown(false);

    getActivity().getSupportLoaderManager().initLoader(0, null, this);  
}

public interface OnActorPhoneNumberListListener {
    void onActorPhoneNumberListSelected(String actorId);
}

@Override
public Loader<List<PhoneNumber>> onCreateLoader(int loaderId, Bundle args) {
    loader= new PhoneNumberDataLoader(getActivity(), actorId);
    return(loader);
}

@Override
public void onLoadFinished(Loader<List<PhoneNumber>> loader, List<PhoneNumber> data) {
    // Now give the data to the adapter
    mAdapter.setData(data);
    mAdapter.notifyDataSetChanged();
    //setListAdapter(mAdapter);

    // Show the list
    if (isResumed()) {
        setListShown(true);
    } else {
        setListShownNoAnimation(true);
    }
}

@Override
public void onLoaderReset(Loader<List<PhoneNumber>> arg0) {
    // TODO Auto-generated method stub
    mAdapter.setData(null); 
}
}

0 个答案:

没有答案