DataBinding遇到的问题,已解决

  • Post author:
  • Post category:其他


关于这个问题,我在论坛上进行讨论,为了方便大家看代码,我将我写的代码贴出来 ,希望大家一起讨论,解决问题.

databinding的基本使用,我这里就不在赘述,大多写的很详细,我这个运行起来没有问题,但是就是界面显示不出来.

  1. 主界面是一个登陆界面,点击登陆按钮进行跳转.这块没有问题

    这是首页的布局

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
            name="user"
            type="com.xiaoxiao.mvpanddatabing.bean.User"/>
    </data>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@={user.userName}"/>

        <EditText
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@{user.password}"/>

        <Button
            android:id="@+id/bt_login"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{user.login}"
            android:text="登录"/>

        <Button
            android:id="@+id/bt_regist"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="@{user.register}"
            android:text="注册"/>
    </LinearLayout>
</layout>

MainActivity的设置,比较简单,ActivityMainBinding是根据布局来设置的.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityMainBinding binding = DataBindingUtil.setContentView(this, activity_main);
        User user = new User("haha","123",this);
        binding.setUser(user);
    }
}

User实体类的设置,在此设置了控件的内容和点击事件.登陆按钮用来做界面跳转

public class User extends BaseObservable{
    public String userName;
    public String password;
    public Activity mActivity;


    public User(String userName, String password,MainActivity mainActivity) {
        this.userName = userName;
        this.password = password;
        mActivity = mainActivity;
    }

    @Bindable
    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
        notifyPropertyChanged(BR.userName);
    }
    @Bindable
    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
        notifyPropertyChanged(BR.password);
    }

    public void login(View view) {
        Toast.makeText(view.getContext(),"点击了登录按钮",Toast.LENGTH_SHORT).show();
        //跳转界面
        Intent intent = new Intent(mActivity,ListViewActivity.class);
        mActivity.startActivity(intent);
    }
    public void register(View view) {
        Toast.makeText(view.getContext(),"点击了注册按钮",Toast.LENGTH_SHORT).show();
    }
}
  1. 登陆之后页面,是一个listview,为其设置适配器.之前在布局中设置适配器,直接在Activity通过findviewbyid()获取的listview变量,之后再添加Adapter,但是没有显示出来.这个demo是我再另一个

    博友

    那看到的,直接下载就可以显示,我写的这个demo跳转过去再显示就一直没成功.不知道是哪里出了问题,后来我直接使用databinding给listview设置适配器还是没有显示.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">
    <data>
        <variable
            name="adapter"
            type="com.xiaoxiao.mvpanddatabing.adapter.MyAdapter"/>

    </data>

    <LinearLayout
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/colorAccent"
            android:text="slkafjda;lsja;f"/>

        <ListView
            android:id="@+id/lv"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:adapter="@{adapter}"/>


    </LinearLayout>
</layout>

Activity的设置:这个listview显示的内容是使用网上的一个demo,不过demo中可以展示出来,我看了好久也没发现哪有问题,我这就是不显示.

public class ListViewActivity extends AppCompatActivity {
    private List<Food> mFoods;
    private MyAdapter<Food> mMyAdapter;
    private  ActivityListBinding binding;
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            binding.lv.setAdapter(mMyAdapter);
            mMyAdapter.notifyDataSetChanged();
        }
    };
    //之所以断点都没有进来,是因为我的oncreate方法写错了,应该是一个参数的,马虎不得啊!
    /**@Override
    public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
        super.onCreate(savedInstanceState, persistentState);
        ActivityListBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_list);
        mFoods = new ArrayList<>();
        mMyAdapter = new MyAdapter<>(this,R.layout.layout_item,mFoods, com.xiaoxiao.mvpanddatabing.BR.food);
        binding.lv.setAdapter(mMyAdapter);//这开始写错了没有加lv
        initData();
    }*/
@Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = DataBindingUtil.setContentView(this, R.layout.activity_list);
        mFoods = new ArrayList<>();
        mMyAdapter = new MyAdapter<>(this,R.layout.layout_item,mFoods, com.xiaoxiao.mvpanddatabing.BR.food);

        initData();
        //binding.lv.setAdapter(mMyAdapter);//在这些不起作用,要在handler中写
    }
    /**
     * 使用okhttp请求网络
     */
    private void initData() {
//      mDialog.show();
        OkHttpClient okHttpClient = new OkHttpClient.Builder().build();
        Request request = new Request.Builder().url("http://www.tngou.net/api/food/list?id=1").build();
        //使用异步请求
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {
                if (response.isSuccessful()) {
                    parserJson(response.body().string());//啊,这也写错了,应该是string()写成toString()了,以后注意
                }
            }
        });
    }

    private void parserJson(String jsonStr) {
        try {
            JSONObject jsonObject = new JSONObject(jsonStr);
            JSONArray tngou = jsonObject.getJSONArray("tngou");
            for(int i = 0;i< tngou.length();i++) {
                JSONObject object = tngou.getJSONObject(i);
                String description = object.getString("description");
                String img = "http://tnfs.tngou.net/image"+object.getString("img");
                String keywords = "【关键词】 "+object.getString("keywords");
                String summary = object.getString("summary");
                mFoods.add(new Food(description,img,keywords,summary));
            }
            mHandler.sendEmptyMessage(0);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

Adapter的设置:这个设置之后可以供多个listview和Gridview使用

public class MyAdapter<T> extends BaseAdapter {
    private Context context;
    private int layoutId;
    private List<T> list;
    private int resId;
    private LayoutInflater mInflater;

    /**
     *
     * @param context   上下文
     * @param layoutId  布局文件的id
     * @param list  实体类的集合
     * @param resId 布局中对应的实体名
     */
    public MyAdapter(Context context, int layoutId, List<T> list ,int resId) {
        this.context = context;
        this.layoutId = layoutId;
        this.list = list;
        this.resId = resId;
        mInflater = LayoutInflater.from(context);
    }
    @Override
    public int getCount() {
        return list.size();
    }

    @Override
    public Object getItem(int i) {
        return list.get(i);
    }

    @Override
    public long getItemId(int i) {
        return i;
    }

    @Override
    public View getView(int i, View view, ViewGroup viewGroup) {
        ViewDataBinding dataBinding;
        if (view == null) {
            dataBinding = DataBindingUtil.inflate(mInflater, layoutId, viewGroup, false);
        }else {
            dataBinding = DataBindingUtil.getBinding(view);
        }
        dataBinding.setVariable(resId,list.get(i));
        return dataBinding.getRoot();
    }
}

Food的实体类,运行时偶尔会提示警告,关于设置img加载图片的方法loadInternetImage().报警告:Application namespace for attribute bind:img will be ignored,但有时就不提示,有说在设置中搜索Unknown Android XML attribute,把勾去掉即可,但之后还是有提示,暂时先不管这个了.

public class Food extends BaseObservable {
    private final ObservableField<String> description = new ObservableField<>();
    private final ObservableField<String> img = new ObservableField<>();
    private final ObservableField<String> keywords = new ObservableField<>();
    private final ObservableField<String> summary = new ObservableField<>();

    public Food() {
    }

    public Food(String description, String img, String keywords, String summary) {
        this.description.set(description);
        this.img.set(img);
        this.keywords.set(keywords);
        this.summary.set(summary);
    }

    @Bindable
    public ObservableField<String> getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description.set(description);
        notifyPropertyChanged(BR.description);
    }

    @Bindable
    public String getImg() {
        return img.get();
    }

    public void setImg(String img) {
        this.img.set(img);
    }

    @Bindable
    public String getKeywords() {
        return keywords.get();
    }

    public void setKeywords(String keywords) {
        this.keywords.set(keywords);
    }

    @Bindable
    public String getSummary() {
        return summary.get();
    }

    public void setSummary(String summary) {
        this.summary.set(summary);
    }


    public void onItemClick(View view) {
        setDescription("111");
    }

    public void clickKeywords(View view) {
        Toast.makeText(view.getContext(), getKeywords(), Toast.LENGTH_SHORT).show();
    }

    @BindingAdapter("bind:img")
    public static void loadInternetImage(ImageView imageVeiw, String img) {
        Picasso.with(imageVeiw.getContext()).load(img).into(imageVeiw);
    }

}

item的布局,设置了点击事件.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto">

    <data>
        <variable
            name="food"
            type="com.xiaoxiao.mvpanddatabing.bean.Food"
            />
    </data>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="96dp"
        android:onClick="@{food.onItemClick}"
        >

        <ImageView
            android:id="@+id/iv"
            android:layout_width="96dp"
            android:layout_height="96dp"
            android:padding="6dp"
            app:img="@{food.img}"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_toRightOf="@id/iv"
            android:ellipsize="end"
            android:maxLines="3"
            android:text="@{food.description}"
            />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="8dp"
            android:layout_toRightOf="@id/iv"
            android:layout_alignParentBottom="true"
            android:layout_marginBottom="2dp"
            android:text="@{food.keywords}"
            android:onClick="@{food.clickKeywords}"
            android:textStyle="bold"
            />
    </RelativeLayout>
</layout>

论坛的网址是

Databinding论坛



另外,如果是双向绑定

这篇文章

写的不错,可以看看.

经过这个联系,更加熟悉databinding的使用了,还需要多练习.



版权声明:本文为u013055213原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。