Communication between TabActivity and the embedded activity

后端 未结 5 799
Happy的楠姐
Happy的楠姐 2021-01-14 15:44

I am trying to figure out the best practice of communication between a TabActivity and the child activity embedded in this TabActivity.

In my TabActivity, there is a

相关标签:
5条回答
  • 2021-01-14 16:41

    You can use getParent() to obviate the need to do any of this.

    Here's my launcher child class with buttons that switch between activities handled by the tabHost:

    public class LaunchPadActivity extends Activity implements OnClickListener {
    
    private static final int ICON_PROFILE = 0;
    
    private static final int ICON_SEARCH = 1;
    
    private static final int ICON_MAP = 2;
    
    private static final int FAVOURITES = 3;
    
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        setContentView(R.layout.launchpad);
    
        GridView launchPad = (GridView) findViewById(R.id.launchpad);
        launchPad.setAdapter(new LaunchIconAdapter(this));
    }
    
    public class LaunchIconAdapter extends BaseAdapter {
        private Context mContext;
    
        // references to our images
        private Integer[] mThumbIds = { R.drawable.user, R.drawable.find,
                R.drawable.map, R.drawable.favourites, R.drawable.reviews,
                R.drawable.news, R.drawable.tutorial, R.drawable.info,
                R.drawable.options, };
    
        public String[] texts = { "Profile", "Search", "Map", "Favourites",
                "Reviews", "News", "Tutorial", "Info", "Options" };
    
        public LaunchIconAdapter(Context c) {
            mContext = c;
        }
    
        // Number of thumbs determines number of GridView items
        public int getCount() {
            return mThumbIds.length;
        }
    
        public Object getItem(int position) {
            return null;
        }
    
        public long getItemId(int position) {
            return 0;
        }
    
        // create a new ImageView for each item referenced by the Adapter
        public View getView(int position, View convertView, ViewGroup parent) {
            // Icon elements
            LinearLayout launchIcon;
            ImageView launchImage;
            TextView launchText;
    
            if (convertView == null) {
                launchIcon = (LinearLayout) ((LayoutInflater) mContext
                        .getSystemService(LAYOUT_INFLATER_SERVICE)).inflate(
                        R.layout.launchicon, null);
    
            } else {
                launchIcon = (LinearLayout) convertView;
            }
    
            // Add ClickListener with metadata
            launchIcon.setTag(new Integer(position));
            launchIcon.setOnClickListener(LaunchPadActivity.this);
    
            // Get subviews
            launchImage = (ImageView) launchIcon
                    .findViewById(R.id.launch_image);
            launchText = (TextView) launchIcon.findViewById(R.id.launch_text);
    
            // Configure subviews
            launchImage.setImageResource(mThumbIds[position]);
            launchText.setText(texts[position]);
    
            return launchIcon;
        }
    
    }
    
    @Override
    public void onClick(View v) {
        int position = ((Integer) v.getTag()).intValue();
        switch (position) {
        case ICON_PROFILE:
            Toast.makeText(this, "Profile", Toast.LENGTH_LONG).show();
            break;
    
        case ICON_SEARCH:
            Toast.makeText(this, "Search", Toast.LENGTH_LONG).show();
            ((TabActivity) getParent()).getTabHost().setCurrentTab(1);
            break;
    
        case ICON_MAP:
            Toast.makeText(this, "Map", Toast.LENGTH_LONG).show();
            ((TabActivity) getParent()).getTabHost().setCurrentTab(2);
            break;
    
        case FAVOURITES:
            Toast.makeText(this, "Map", Toast.LENGTH_LONG).show();
            ((TabActivity) getParent()).getTabHost().setCurrentTab(3);
            break;
    
        }
    
    }
    
    }
    

    Works like a charm.

    0 讨论(0)
  • 2021-01-14 16:42

    Since TabActivity is an ActivityGroup, I would use one of the following:

    • getCurrentActivity()

    Returns the child tab activity being displayed. In your case, this method will return the instance of ChildActivity being used.

    ChildActivity childActivity = (ChildActivity) getCurrentActivity();
    
    • getLocalActivityManager().getActivity(String)

    Returns the child tab activity given its ID/tab spec name, whatever activity being displayed.

    ChildActivity childActivity = (ChildActivity) getLocalActivityManager().getActivity("Tab 1");
    

    I suggest overriding onNewIntent(Intent) in your ChildActivity:

    Intent intent = new Intent();
    intent.putExtra("xyz", "whatever"); // or a serializable
    
    ChildActivity childActivity = (ChildActivity) getLocalActivityManager().getActivity("Tab 1");
    childActivity.onNewIntent(intent);
    

    Let me know if it works!

    0 讨论(0)
  • 2021-01-14 16:45

    Couple of design issues with this, but overall it seems reasonable.

    I would forgo the static instance in the ChildActivity class. Why? Well, think about the relationship you're modeling. A TabActivity has a ChildActivity. This is textbook composition, and would be accomplished by adding a ChildActivity field to the TabActivity class, like so:

     public class TabActivity {
    
        private ChildActivity child;
    
        //remember to initialize child in onCreate
    
        //then, call methods using child.changeUI();, for example
    
    } 
    

    This is better, because A) now I can have multiple instances of TabActivity and ChildActivity that won't interfere with each other (before, it was just a static variable, so only one ChildActivity could be used), and B) the ChildActivity is encapsulated inside the TabActivity class... before, it was a public field, meaning anything can use and modify it (might not be desirable; can often lead to some strange runtime bugs as well as messy, tied-together code) - we changed it to a private field, because we don't really want other classes accessing it in unexpected ways.

    The only thing you may need access to from the ChildActivity is the parent (TabActivity). To do this, add the following methods and field to the ChildActivity class, and call the registerParent() method after constructing the ChildActivity:

    public class ChildActivity ...{
    
    private TabActivity parent;
    
    public void registerParent(TabActivity newParent){
        if (newParent != null){
            parent = newParent;
        }
    }
    }
    

    So, if you need access to the parent TabActivity from the child, just call parent.someMethod();

    It would also be wise to access fields like parent and child through getters and setters; it might save you some time in the long run.

    0 讨论(0)
  • 2021-01-14 16:46

    The way above with

    ChildActivity childActivity = (ChildActivity) getLocalActivityManager().getActivity("Tab 1");
    childActivity.onNewIntent(intent);
    

    is not very nice. Instead of invoking your activity method directly (it can be null!!!) better do it this way:

    Intent intent = new Intent(this, ChildActivity.class);
    intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
    intent.putExtra(AlbumBrowser.INTENT_EXTRA_FILTER, mediaTitle);
    getLocalActivityManager().startActivity("activityIdHere", intent);
    
    0 讨论(0)
  • 2021-01-14 16:48

    Seems fine. A couple of notes:
    - I see no reason for synchronization.
    - I'd replace

    ChildActivity.s_childActivity.changeUI();
    

    with

    if(ChildActivity.s_childActivity != null){
        ChildActivity.s_childActivity.changeUI();
    }
    

    or even

    try{
        ChildActivity.s_childActivity.changeUI();
    } catch(Exception e){
        //log
    }
    

    for added paranoid safety. :)

    0 讨论(0)
提交回复
热议问题