关于这个问题,我在论坛上进行讨论,为了方便大家看代码,我将我写的代码贴出来 ,希望大家一起讨论,解决问题.
databinding的基本使用,我这里就不在赘述,大多写的很详细,我这个运行起来没有问题,但是就是界面显示不出来.
-
主界面是一个登陆界面,点击登陆按钮进行跳转.这块没有问题
这是首页的布局
<?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();
}
}
-
登陆之后页面,是一个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的使用了,还需要多练习.