DataBinding遇到的問題,已解決

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章