18

I have a simple Activity with TabLayout, ViewPager and 2 Fragments in it. Here's my Activity:

public class ManagementCompanyOverviewActivity extends BaseActivity implements ManagementCompanyOverviewView {

    private ManagementCompanyVPAdapter mVPAdapter;
    private TabLayout mTLContent;
    private ViewPager mVPContent;

    @InjectPresenter
    ManagementCompanyPresenter mPresenter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_management_company);

        mVPAdapter = new ManagementCompanyVPAdapter(getSupportFragmentManager());

        mTLContent = (TabLayout) findViewById(R.id.tl_company_content);

        mVPContent = (ViewPager) findViewById(R.id.vp_company_content);
        mVPContent.setAdapter(mVPAdapter);
        mTLContent.setupWithViewPager(mVPContent);
    }

    @Override
    public void onAboutCompanyInfoReceivedFromServer(AboutCompanyViewModel model) {

    }

Activity has a Presenter (I'm using Moxy), Presenter sends request, gets answer, creates JavaObject (view model) and with getViewState() passes this model to activity. I need to pass this model from Activity to one of my Fragments.

Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_about_company, container, false);

    mTVName = (TextView) view.findViewById(R.id.tv_company_name);
    mTVDirector = (TextView) view.findViewById(R.id.tv_company_director);
    mTVWebsite = (TextView) view.findViewById(R.id.tv_company_website);
    mTVEmail = (TextView) view.findViewById(R.id.tv_company_email);
    mTVPhone = (TextView) view.findViewById(R.id.tv_company_phone);
    mTVSchedule = (TextView) view.findViewById(R.id.tv_company_schedule);
    mTVAddress = (TextView) view.findViewById(R.id.tv_company_address);

    return view;
}

This fragment has some TextViews to show the info from my model. How to pass this model? If I know it right I should create a listener, but how? I don't completely understand how to work with em.

Den
  • 1,284
  • 2
  • 14
  • 33

8 Answers8

22

Okay, I did this.

1 step: I created public interface in my Activity and setter for it:

private OnAboutDataReceivedListener mAboutDataListener;

public interface OnAboutDataReceivedListener {
        void onDataReceived(AboutCompanyViewModel model);
    }

public void setAboutDataListener(OnAboutDataReceivedListener listener) {
    this.mAboutDataListener = listener;
}

2 step: I implemented this interface in my Fragment and set listener:

public class AboutCompanyFragment extends BaseFragment implements ManagementCompanyOverviewActivity.OnAboutDataReceivedListener

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

            mActivity = (ManagementCompanyOverviewActivity) getActivity();
            mActivity.setAboutDataListener(this);
        }

3 step: I overrided interface's method:

@Override
    public void onDataReceived(AboutCompanyViewModel model) {
        mPBName.setVisibility(View.INVISIBLE);
        mPBDirector.setVisibility(View.INVISIBLE);
        mPBWebsite.setVisibility(View.INVISIBLE);
        mPBEmail.setVisibility(View.INVISIBLE);
        mPBPhone.setVisibility(View.INVISIBLE);
        mPBSchedule.setVisibility(View.INVISIBLE);
        mPBAddress.setVisibility(View.INVISIBLE);

        mTVName.setVisibility(View.VISIBLE);
        mTVDirector.setVisibility(View.VISIBLE);
        mTVWebsite.setVisibility(View.VISIBLE);
        mTVEmail.setVisibility(View.VISIBLE);
        mTVPhone.setVisibility(View.VISIBLE);
        mTVSchedule.setVisibility(View.VISIBLE);
        mTVAddress.setVisibility(View.VISIBLE);

        mTVName.setText(model.getCompanyName());
        mTVDirector.setText(model.getDirectorName());
        mTVWebsite.setText(model.getWebsite());
        mTVEmail.setText(model.getEmail());
        mTVPhone.setText(model.getPhone());
        mTVSchedule.setText(model.getWorkTime());
        mTVAddress.setText(model.getAddress());
    }

That's it.

Den
  • 1,284
  • 2
  • 14
  • 33
6

Try this In activity

public String sendData() {
        return YOUR_STRING;
    }

In Fragment

YOUR_ACTIVITY activity = (YOUR_ACTIVITY) getActivity();
String getData = activity.SendData();
MKovac
  • 176
  • 1
  • 8
  • Nope, not gonna work. Data comes from the server and it can be received in 3-5 seconds. Method public void onAboutCompanyInfoReceivedFromServer(AboutCompanyViewModel model) is called when my Activity received this data. – Den Sep 05 '17 at 08:27
  • Activity should send data to fragment, when the data is ready. I can't use getter. – Den Sep 05 '17 at 08:29
  • 1
    You can try setupViewPager when you receive data, i did like that in my app – MKovac Sep 05 '17 at 08:31
  • Can you post some example code? Just edit your first answer :) – Den Sep 05 '17 at 08:32
  • I don't know where you are getting data. I'm using AsyncTask and when task is finished i call setupViewPager. Just put mTLContent.setupWithViewPager(mVPContent); to method where you get data response – MKovac Sep 05 '17 at 08:34
  • Well, this is not my case I guess. I need to init fragments from the start and show progress bars in every field till the data received. – Den Sep 05 '17 at 08:42
  • You can show progress bar until you don't receive data. I hope someone will have some other solution for you :) – MKovac Sep 05 '17 at 08:46
6

You can use newInstance method in your Fragment:

public static MyFragment newInstance(String parameter) {

        Bundle args = new Bundle();
        args.putString("parameter", parameter);
        SfCategoryFragment fragment = new SfCategoryFragment();
        fragment.setArguments(args);
        return fragment;
    }

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

        if (getArguments() != null) {
            parameter = getArguments().getString("parameter");
        }
    }

And in your Activity:

instead of new MyFragment() use MyFragment.newInstance("yourParam");

Hamidreza Samadi
  • 637
  • 1
  • 7
  • 24
3

You could also in your adapter's constructor take in the data you want to display in the fragment and set the arguments before returning a new fragment

public class ViewPagerAdapter extends FragmentStatePagerAdapter {
private Weather weather;

ViewPagerAdapter(FragmentManager fm, Weather weather) {
    super(fm);
    this.weather = weather;
}

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            Bundle bundle = new Bundle();
            WeatherFragment weatherFragment = new WeatherFragment();
            bundle.putParcelable("weather", weather);
            weatherFragment.setArguments(bundle);
            return weatherFragment;
        case 1:
            return new PoemFragment();
        default:
            return new EmptyFragment();
    }
}
2

From Activity or ViewPager

Bundle bundle = new Bundle();
bundle.putParcelable(Keys.KEY_ITEM, cardResult);
CardItemFragment cardItemFragment = new CardItemFragment();
cardItemFragment.setArguments(bundle);

From Fragment

@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
     getBundle();
}


private void getBundle() {
    bundle = getArguments();
    if (null != bundle) {
        if (bundle.containsKey(Keys.KEY_ITEM)) {
            cardResult = bundle.getParcelable(Keys.KEY_ITEM);
        }
    }
}
Zoe
  • 27,060
  • 21
  • 118
  • 148
Ahamadullah Saikat
  • 4,437
  • 42
  • 39
2

Fragment

class SampleFragment : Fragment(), BaseFragmentInteraction {
    override fun updateFragmentData(data: String) {
        Toast.makeText(activity!!, data, Toast.LENGTH_SHORT).show()
    }
}

Interface

interface BaseFragmentInteraction {
    fun updateFragmentData(data: String)
}

Activity:

view_pager.addOnPageChangeListener(object : ViewPager.OnPageChangeListener {

        override fun onPageSelected(position: Int) {
            val fragmentItem = (view_pager.adapter as FragmentPagerAdapter).getItem(view_pager.currentItem)
            (fragmentItem as BaseFragmentInteraction).updateFragmentData("SomeData")
        }

        override fun onPageScrollStateChanged(state: Int) {}

        override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {}
    })

The updateFragmetData method will be called in the current selected viewpager item fragment. You can also add a tag parameter to updateFragmetData so that you can be sure the right fragment instance is called. If required you can call isVisible in updateFragmetData implementation to make sure the fragment is visible.

Sai
  • 15,188
  • 20
  • 81
  • 121
0

I found a new way to pass data to fragment , or fragments adapter directly

first you make a getter method for getting data Supose you want to get username you make a method in activity

public String getUsername(){
return username;
}

then you call this method from fragment as well as from fragment adapter like this

Fragment

(MainActivity) getActivity()).getUsername()

Adapter

(MainActivity) context).getUsername()

this way also help you to decrease number of request to database

Adnan Bashir
  • 645
  • 4
  • 8
  • 1
    What if your Fragment is used in another Activity? You always should use interfaces to re-use your code. – Den Jul 12 '21 at 15:18
  • You are 100% right but we are talking about data passing from activity to fragment , definitely if you need data in other activity which is not in running state then you must use Interfaces – Adnan Bashir Jul 12 '21 at 18:23
  • Anyway, in my original post the case is the activity receives some data from the internet and this activity should send this data to fragments, getters will not help in this case. – Den Jul 13 '21 at 07:00
0

you can pass data from the activity to the fragment or any fragment you want in 2 simple steps (when using the FragmentStatePagerAdapter):

Step 1:pass data from Activity to ViewPagerAdapter class: to do that you need to add another attribut(s) to the constructor (attribut==your data)

Step 2:pass the data from viewPagerAdapter class to fragment:and now in the createFragment() function you can pass that attribut using a bundle

Finally: recieve the data in the fragment

Zineddine
  • 1
  • 1