masmic
masmic

Reputation: 3574

Code translations from activity to fragment

I'm making a conversion from 2 clases that extends ListActivity to extend ListFragment due to code proposals.

As I know, the Fragment is related to the Activity, so at first using getActivity()... should do the work to adapt most methods. Other times, I've defined Activity activity_context; and I use this.

Anyway, I have some functions that I'm not able to adapt, and I would need some help.

The first is: RecentCallsListActivity extends Fragment

public class RecentCallsListActivity extends ListFragment
...

private static final class QueryHandler extends AsyncQueryHandler {
    private final WeakReference<RecentCallsListActivity> mActivity;
    ...

public QueryHandler(Context context) {
        super(context.getContentResolver());
        mActivity = new WeakReference<RecentCallsListActivity>(
                (RecentCallsListActivity) context); //GETTING THE ERROR HERE
    }

ERROR: Cannot cast from context to RecenCallsListActivity

public void onActivityCreated(Bundle state) {
    super.onActivityCreated(state);

    mQueryHandler = new QueryHandler(activity_context);

The second is: CallDetailActivity extends Fragment

public class CallDetailActivity extends ListFragment
...

public boolean onKeyDown(int keyCode, KeyEvent event) {
    switch (keyCode) {
        case KeyEvent.KEYCODE_CALL: {
            // Make sure phone isn't already busy before starting direct call
            TelephonyManager tm = (TelephonyManager)
                    getActivity().getSystemService(Context.TELEPHONY_SERVICE);
            if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
                Intent callIntent = new Intent(Intent.ACTION_CALL,
                        Uri.fromParts("tel", mNumber, null));
                startActivity(callIntent);
                return true;
            }
        }
    }

    return super.onKeyDown(keyCode, event);  //GETTING IT HERE
}

ERROR: The method onkeyDown(int, keyevent) is undefined for the type ListFragment

Upvotes: 0

Views: 575

Answers (1)

gunar
gunar

Reputation: 14710

  1. QueryHandler
    At runtime you're providing a class that is not a RecentCallsListActivity or extend from it. The way of handling this is to define an interface that exposes an API that should be implemented by parent activity. If you have multiple activities that need to implement this interface and have the same implementation, you can make a super Activity that implements your interface and each of your activity will extend from this super class. But if you have a single class don't need to do this.
  2. onKeyDown handling - as you can see from API, the fragment doesn't expose any onKeyDown. I have some ideas why this was not implemented, but you can delegate this action from activity to fragment, so that if the fragment is not present and it doesn't wish to consume the event, then you can call activity's super.onKeyDown.

Maybe some code will provide some light and will be helpful.

Sample fragment class:

public class QueryFragment extends Fragment {
    public static interface RecentCallsLister {
        public void someAction();
    }

    private RecentCallsLister recentCallsListener;

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        if (activity instanceof RecentCallsLister) {
            this.recentCallsListener = (RecentCallsLister) activity;
        } else {
            throw new ClassCastException("Parent class does not implement RecentCallsLister");
        }
    }

    @Override
    public void onDetach() {
        this.recentCallsListener = null;
        super.onDetach();
    }

    public boolean manageOnKeyDown(int keyCode, KeyEvent event) {
        if(keyCode == KeyEvent.KEYCODE_CALL) {
            // your specific code
            return true;
        }
        return false;
    }
}

Sample parent activity class:

public class QueryParentActivity extends FragmentActivity implements RecentCallsLister {
    private static final String QUERY_FRAGMENT_TAG = "QUERY_FRAGMENT_TAG";

    protected void addQueryFragment() {
        QueryFragment fragment = new QueryFragment();
        getSupportFragmentManager().beginTransaction()
                .add(R.id.where_do_want_to_have_me, fragment, QUERY_FRAGMENT_TAG).commit();
    }

    @Override
    public void someAction() {

    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (queryFragmentConsumedKeyDown(keyCode, event)) {
            return true;
        }
        return super.onKeyDown(keyCode, event);
    }

    private boolean queryFragmentConsumedKeyDown(int keyCode, KeyEvent event) {
        FragmentManager fm = getSupportFragmentManager();
        Fragment fragment = fm.findFragmentByTag(QUERY_FRAGMENT_TAG);
        if (fragment != null) {
            return ((QueryFragment) fragment).manageOnKeyDown(keyCode, event);
        }
        return false;
    }
}

EDIT for your first issue:
replace the QueryHandler constructor from:

public QueryHandler(Context context) {
    super(context.getContentResolver());
    mActivity = new WeakReference<RecentCallsListActivity>((RecentCallsListActivity) context);
    }

to:

public QueryHandler(Context context, RecentCallsListActivity fragmentInstance) {
    super(context.getContentResolver());
    mActivity = new WeakReference<RecentCallsListActivity>(fragmentInstance);
}

Instantiate it as: mQueryHandler = new QueryHandler(activity_context, this);

Upvotes: 1

Related Questions