I have a fragment view that needs replacement with another fragment.
When the ListFragment item is selected, the DetailsFragment is to be replaced with another ListFragment by passing along Extras to the new ( or 2nd) ListFragment in the activity. My problem is that I am getting a “No Activity found to handle Intent {(has extras)}”. The ListFragment works fine when the activity first starts, but when i up date (replace) the Details activity with another ListFragment, I get the error.
This is my first Fragment activity and I guess I don’t know how to pass Extras properly between the fragment. I am most surely not using the fragment-manager/transaction classes properly(?). If anyone could correct my implementation, I would greatly appreciate it.
UPDATE: I added “i.setClass(getActivity(), ListFragment.class);” to the intent in the ListFragment class and now the Log error has changed to the following:
UPDTATE 2: I corrected my intents to Arguments as Devunwired sugested and it works just beautifully now. Thnx Devunwired. the onlyn issue I have now is that the backstack doesnt work when the back key is pressed. The corrected class is below:
LogCat (UPDATED):
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.andaero.test/com.andaero.test.fragments.ListFragment}: java.lang.ClassCastException: com.andaero.test.fragments.ListFragment cannot be cast to android.app.Activity
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1739)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1831)
at android.app.ActivityThread.access$500(ActivityThread.java:122)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1024)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4123)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.ClassCastException: com.andaero.test.fragments.ListFragment cannot be cast to android.app.Activity
The ListFragment Class:
public class ListFragment extends android.app.ListFragment {
boolean mDualPane;
int mCurCheckPosition = 0;
protected TextView activityTitle;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String extStorageDirectory = Environment.getExternalStorageDirectory()
.toString();
File dbfile = new File(extStorageDirectory + "/Andaero/dB/Andaero.db");
SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(dbfile, null);
private static final String QUERY_KEY = "QUERY_KEY";
private static final String QUERY_ORDER = "QUERY_ORDER";
private View layout;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
layout = inflater.inflate(R.layout.listview, null);
return layout;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
Bundle extras = getActivity().getIntent().getExtras();
Bundle arg = this.getArguments();//**ADDED TO GET THE ARGS
/**
* Get the query string from last activity and pass it to this
* activity-----------------------------------------------------
*/
String q = null;
if (extras != null) {
q = extras.getString(QUERY_KEY);
}
if (arg != null) {
q = (String) (getArguments() != null ? getArguments().getString(
"QUERY_KEY") : 1);
}
loadQuery(q);
}
public void loadQuery(String q) {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
String qO = getActivity().getIntent().getStringExtra("QUERY_ORDER");
Cursor c = db.rawQuery(q + " ORDER BY `_id` " + qO, null);
setListAdapter(new QueryAdapter(getActivity(), c));
db.close();
} else {
Alerts.sdCardMissing(getActivity());
}
}
public class QueryAdapter extends CursorAdapter {
public QueryAdapter(Context context, Cursor c) {
super(context, c);
LayoutInflater.from(context);
}
@Override
public void bindView(View v, Context context, final Cursor c) {
int tvLabel = c.getColumnIndexOrThrow("label");
String label = c.getString(tvLabel);
final TextView labelTxt = (TextView) v.findViewById(R.id.label);
if (labelTxt != null) {
labelTxt.setText("(" + label + ")");
}
int tvTitle = c.getColumnIndexOrThrow("title");
final String title = c.getString(tvTitle);
TextView titleTxt = (TextView) v.findViewById(R.id.listTitle);
if (titleTxt != null) {
titleTxt.setText(title);
}
int tvDescription = c.getColumnIndexOrThrow("description");
String description = c.getString(tvDescription);
TextView descriptionTxt = (TextView) v.findViewById(R.id.caption);
if (descriptionTxt != null) {
descriptionTxt.setText(description);
}
int tvDate = c.getColumnIndexOrThrow("date");
String date = c.getString(tvDate);
TextView dateTxt = (TextView) v.findViewById(R.id.dateAdded);
if (dateTxt != null) {
dateTxt.setText(date);
}
int tvGoto = c.getColumnIndexOrThrow("gotoURL");
final String gotoURL = c.getString(tvGoto);
TextView gotoTxt = (TextView) v.findViewById(R.id.dummy);
if (gotoTxt != null) {
gotoTxt.setText(gotoURL);
}
gotoTxt.setVisibility(View.GONE);
v.setTag(gotoURL);
final ListView lv = getListView();
lv.setEnabled(true);
lv.setClickable(true);
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View v, int arg2,
long arg3) {
// Create new fragment and transaction
Fragment newFragment = new ListFragment();
FragmentTransaction transaction = getFragmentManager()
.beginTransaction();
// Replace whatever is in the fragment_container view with
// this fragment,
// and add the transaction to the back stack
transaction.replace(R.id.detailFragment, newFragment);
transaction.addToBackStack(null);
String url = "";
url = (String) v.getTag();
int nI = c.getColumnIndexOrThrow("intent");
String intent = c.getString(nI);
Class<?> myIntent = null;
try {
myIntent = Class.forName("com.andaero.test.fragments"
+ intent);
} catch (ClassNotFoundException e) {
Log.e("ERROR", "Class Not Found for new intent!");
e.printStackTrace();
}
int tvTitle = c.getColumnIndexOrThrow("title");
String title = c.getString(tvTitle);
int tvLabel = c.getColumnIndexOrThrow("label");
String label = c.getString(tvLabel);
String queryKey = "SELECT * FROM " + label;
c.close();
db.close();
Bundle args = new Bundle();//**REPLACED THE INTENTS
args.putString("QUERY_KEY", queryKey);
args.putString("KEY_URL", url);
args.putString("KEY_SUBTITLE", title);
args.putString("KEY_LABEL", label);
args.putString("KEY_INTENT", intent);
args.putString("QUERY_ORDER", "ASC");
newFragment.setArguments(args);
// Commit the transaction
transaction.commit();
}
});
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
final View v = LayoutInflater.from(context).inflate(
R.layout.list_item, parent, false);
return v;
}
}
}
You’re on the right track with using the
FragmentTransactionto replace oneFragmentwith another, butFragmentdoesn’t use anIntentto pass data from one instance to another likeActivitydoes. In fact, callingstartActivity()with anIntentpointed at aFragmentwill cause all kinds of fireworks that you don’t want (like you’ve seen).It is perfectly okay to pass data to a new
Fragmentin its constructor, so you can create a constructor for yourListFragmentthat takes any parameters of data you want to forward. Another option is to set all of your “extras” as arguments on the newFragmentby putting them in aBundleand usingFragment.setArguments(). Any time you want to access the arguments you attached to theFragment, you can just callgetArguments()to get back that sameBundle. So basically, replace all the code having to do with anIntentin youronItemClick()method, and instead:Also, off-topic, but you might want to rename your
Fragmentto something else so that you don’t have to rely on the fully qualified package name to tell the difference between yourListFragmentand the platform’s version in your code.HTH