關於這個問題,我在論壇上進行討論,爲了方便大家看代碼,我將我寫的代碼貼出來 ,希望大家一起討論,解決問題.
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的使用了,還需要多練習.