简体   繁体   中英

Two way binding Android

Maybe I am missing something small here, but I cannot get my binding to work. I set it up as follow:

public class Toolbar extends Fragment {

//Interaction handlers
//interface for interaction with Activity
public interface ToolBarInteraction{
    public void Search(String screenName);
}

private ToolbarBind modelData;
private ToolBarInteraction mListener;

public static Toolbar newInstance() {
    return new Toolbar();
}

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

    FragmentToolbarBinding binding = DataBindingUtil.setContentView(getActivity(), R.layout.fragment_toolbar);
    modelData = ToolbarBind.newInstance();
    modelData.searchedText.set("Hello");
    binding.setModelData(modelData);
}

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

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

    //get button to set onClick event
    Button button = (Button)view.findViewById(R.id.btnSearch);
    button.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String hello = modelData.searchedText.get();
        }
    });

    return view;
}

public void OnSearchClicked(View view){
    mListener.Search(modelData.searchedText.get());
}

private void checkMListener(){
    try{
        mListener = (ToolBarInteraction) getActivity();
    } catch (ClassCastException ex) {
        throw new ClassCastException(getActivity().toString()
                + " must implement the ToolBarInteraction Interface");
    }
}
}

Here is the code for ToolbarBind:

public class ToolbarBind extends BaseObservable {
private String _searchText;

public final ObservableField<String> searchedText = new ObservableField<String>();

//factory method
public static ToolbarBind newInstance(){ return new ToolbarBind(); }
}

And in my fragment, I set the binding up as follow, all within the layout tag:

<data>
    <variable
        name="modelData"
        type="Common.CommonObjects.ToolbarBind"/>
</data>

And for binding to property:

<EditText
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:hint="Search"
     android:text="@={modelData.searchedText}"/>

As can be seen, in the onCreate I set the text to "Hello", but even when the view displays on the phone, the EditText is not populated with this text. When I change the value, and click my button, the value I get back in the event is "Hello", not my new text entered while the app is running.

What am I missing?

The problem with your code is that you set the Activity 's content view to something in onCreate(...) but you inflate and use something different in onCreateView(...) as your fragment's view, which gets the model data (not the other one you created in onCreate(...) ). I don't know exactly what you try to achieve, but I'm gonna guess that you don't want to change the Activity 's content view to something from the fragment, so I'm just gonna show you a variation of what could you use, however, you should change it to whatever pleases you.

Remove onCreate(...) completely then use only onCreateView(...) to inflate the fragment_toolbar layout using data binding:

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

    FragmentToolbarBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_toolbar, container, false);

    // FIXME you're losing data here; watch out: checking whether savedInstanceState == null is not enough because returning from backstack it will be null
    modelData = ToolbarBind.newInstance();

    // FIXME modify this so it sets the data from savedInstanceState when configuration changes
    modelData.searchedText.set("Hello");


    binding.setModelData(modelData);

    //get button to set onClick event
    binding.btnSearch.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            String hello = modelData.searchedText.get();
        }
    });

    return binding.getRoot();
}

Watch out for the FIXME parts. You could move the modelData init to onCreate(...) which would save it from the backstack-return thing, however, configuration change will still call onCreate(...) unless you call setRetainInstance(true) on the fragment ( do not ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM