I have a recycler view, that is picking the data from an URL and it stores it, but I want to set an OnClickListener so I can click on a specific field and show some extra data.
I tried to implement a ClickListener but it gives me an error.
if this way I tried is not good feel free to suggest a better way for my code.
Adapter Class:
package com.example.zlatnakopackajson1;
import android.content.Context;
import android.content.Intent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class PonudiAdapter extends RecyclerView.Adapter<PonudiViewHolder> {
private Context context;
ArrayList<Ponudi> ponudis;
public PonudiAdapter() {
ponudis = new ArrayList<>();
}
public void setData(ArrayList<Ponudi> ponudis) {
this.ponudis = ponudis;
}
#NonNull
#Override
public PonudiViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
Context context = parent.getContext();
LayoutInflater layoutInflater = LayoutInflater.from(context);
View ponudiView = layoutInflater.inflate(R.layout.adapter_view_layout,parent,false);
return new PonudiViewHolder(ponudiView);
}
#Override
public void onBindViewHolder(#NonNull PonudiViewHolder holder, int position) {
final Ponudi ponudi = ponudis.get(position);
// holder.sh_sport_id.setText(ponudi.sh_sport_id);
if ( ponudi.sh_sport_id.equals("1")) {
holder.sh_sport_id.setText("Фудбал");
holder.imgSport.setImageResource(R.drawable.fudbal);
}
else if (ponudi.sh_sport_id.equals("2") ) {
holder.sh_sport_id.setText("Хокеј");
holder.imgSport.setImageResource(R.drawable.hokej);
}
else if (ponudi.sh_sport_id.equals("3") ) {
holder.sh_sport_id.setText("Кошарка");
holder.imgSport.setImageResource(R.drawable.basketball);
}
else if (ponudi.sh_sport_id.equals("4") ) {
holder.sh_sport_id.setText("Тенис");
holder.imgSport.setImageResource(R.drawable.tenis);
}
else if (ponudi.sh_sport_id.equals("5") ) {
holder.sh_sport_id.setText("Ракомет");
// holder.imgSport.setImageResource(R.drawable.handball);
}
else if (ponudi.sh_sport_id.equals("6") ) {
holder.sh_sport_id.setText("MLB");
// holder.imgSport.setImageResource(R.drawable.mlb);
}
else if (ponudi.sh_sport_id.equals("7") ) {
holder.sh_sport_id.setText("Одбојка");
holder.imgSport.setImageResource(R.drawable.odbojka);
}
else if (ponudi.sh_sport_id.equals("8") ) {
holder.sh_sport_id.setText("Рагби");
holder.imgSport.setImageResource(R.drawable.ragbi);
}
else if (ponudi.sh_sport_id.equals("9") ) {
holder.sh_sport_id.setText("Формула");
// holder.imgSport.setImageResource(R.drawable.formula);
}
else if (ponudi.sh_sport_id.equals("10") ) {
holder.sh_sport_id.setText("Мото Спорт");
// holder.imgSport.setImageResource(R.drawable.moto);
}
else if (ponudi.sh_sport_id.equals("11") ) {
holder.sh_sport_id.setText("Ватерполо");
holder.imgSport.setImageResource(R.drawable.vaterpolo);
}
else if (ponudi.sh_sport_id.equals("12") ) {
holder.sh_sport_id.setText("Бокс");
// holder.imgSport.setImageResource(R.drawable.boks);
}
else if (ponudi.sh_sport_id.equals("13") ) {
holder.sh_sport_id.setText("Футсал");
holder.imgSport.setImageResource(R.drawable.futsal);
}
else if (ponudi.sh_sport_id.equals("14") ) {
holder.sh_sport_id.setText("Пинг Понг");
// holder.imgSport.setImageResource(R.drawable.tenis);
}
else {
holder.sh_sport_id.setText("Останато");
holder.imgSport.setImageAlpha(0);
}
holder.tim1.setText(ponudi.tim1);
holder.tim2.setText(ponudi.tim2);
holder.liga_header.setText(ponudi.liga_header);
holder.parent_layout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context,MatchActivity.class);
context.startActivity(intent);
}
});
}
#Override
public int getItemCount() {
return ponudis.size();
}
}
ViewHolder Class:
package com.example.zlatnakopackajson1;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
public class PonudiViewHolder extends RecyclerView.ViewHolder {
TextView sh_sport_id;
TextView tim1;
TextView tim2;
TextView liga_header;
ImageView imgSport;
LinearLayout parent_layout;
public PonudiViewHolder(#NonNull View itemView) {
super(itemView);
sh_sport_id = itemView.findViewById(R.id.textView1);
tim1 = itemView.findViewById(R.id.textView2);
tim2 = itemView.findViewById(R.id.textView3);
liga_header = itemView.findViewById(R.id.textView4);
imgSport = itemView.findViewById(R.id.imgSport);
parent_layout = itemView.findViewById(R.id.parent_layout);
}
}
Error Logcat:
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.content.Context.getPackageName()' on a null object reference
at android.content.ComponentName.<init>(ComponentName.java:131)
at android.content.Intent.<init>(Intent.java:6510)
at com.example.zlatnakopackajson1.PonudiAdapter$1.onClick(PonudiAdapter.java:114)
at android.view.View.performClick(View.java:7125)
at android.view.View.performClickInternal(View.java:7102)
at android.view.View.access$3500(View.java:801)
at android.view.View$PerformClick.run(View.java:27336)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
New Activity:
package com.example.zlatnakopackajson1;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class MatchActivity extends AppCompatActivity {
private static final String TAG = "MatchActivity";
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_match);
Log.d(TAG, "OnCrate: started");
getIncomingIntent();
}
private void getIncomingIntent() {
Log.d(TAG, "getIncomingIntent: checking for incoming intent");
if (getIntent().hasExtra("tim1") && getIntent().hasExtra("tim2")) {
Log.d(TAG, "getIncomingIntetnt: found intent extras.");
String tim1 = getIntent().getStringExtra("tim1");
String tim2 = getIntent().getStringExtra("tim2");
setItems(tim1,tim2);
}
}
private void setItems (String tim1, String tim2) {
Log.d(TAG,"setItems: setting the tims to widgets.");
TextView Tim1 = findViewById(R.id.txtMatchT1);
Tim1.setText(tim1);
TextView Tim2 = findViewById(R.id.txtMatchT2);
Tim2.setText(tim2);
}
}
Here in your PonudiAdapter class you have a private member Context.
But you are not setting the value for the context in your class constructor.
Change your class constructor to pass a context object
public class PonudiAdapter extends RecyclerView.Adapter<PonudiViewHolder> {
private Context context;
ArrayList<Ponudi> ponudis;
public PonudiAdapter(Context context) {
ponudis = new ArrayList<>();
this.context = context;
}
...
}
Then in your class where you initialize the PonudiAdapter, pass the application context.
PonudiAdapter adapter = new PonudiAdapter(getApplicationContext());
Hope this answers your question. Please feel free to comment in case you run into any other issues.
Related
I have an Activity with a RecyclerView which display Livedata from a room database.
My aim is to start a new Activity with more data from the room database when the user is clicking on the corresponding item in the RecyclerView.
For that I overwrote the onClick() method in the adapter of the RecylcerView. Each object of the RecyclerView has a Id, I need that Id to get the corresponding data from the database. So I passed the Id from the Adapter to the Activity.
To search an element by Id in the database that I need the ViewModel object in the MainAcitivty. It is initialized in the onCreate() of the Activity. The method I called in the Adapter is outside the onCreate() and I get a null object reference exception when I try to use it.
How can I use the ViewModel outside of the onCreate() method of the Activity? Or is there another way to search for the element in the database?
Thank you!
The Adapter class:
In the onClick() method is the relevant part.
package com.example.fillmyplate.activities;
import android.content.Context;
import android.graphics.Color;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.fillmyplate.R;
import com.example.fillmyplate.entitys.Recipe;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
class RecipeAdapter extends RecyclerView.Adapter<RecipeAdapter.RecipeViewHolder> {
private static final String TAG = "RecipeAdapter";
private List<Recipe> mRecipes = new ArrayList<>();
private LayoutInflater mInflater;
private Context mContext;
private MainActivity mainActivity = new MainActivity();
private static int backGroundIndex = 0;
class RecipeViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public final TextView recipeTitleItemView;
ImageView imageView;
public RecipeViewHolder(View itemView) {
super(itemView);
recipeTitleItemView = itemView.findViewById(R.id.name);
imageView = itemView.findViewById(R.id.card_image_view);
Log.d(TAG, "RecipeViewHolder: index " + backGroundIndex);
if (backGroundIndex == 0) {
imageView.setImageResource(R.drawable.background_green);
backGroundIndex++;
} else if (backGroundIndex == 1 ) {
imageView.setImageResource(R.drawable.background_red);
backGroundIndex++;
} else if (backGroundIndex == 2 ) {
imageView.setImageResource(R.drawable.background_blue);
backGroundIndex = 0;
}
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
// This should be the mistake.
mainActivity.startKnownRecipeActivity(position);
}
}
public RecipeAdapter(Context context) {
mInflater = LayoutInflater.from(context);
this.mContext = context;
}
#NonNull
#Override
public RecipeAdapter.RecipeViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
// Inflate an item view
View mRecipeTitleView = mInflater.inflate(
R.layout.recipe_list_row, parent, false);
return new RecipeViewHolder(mRecipeTitleView);
}
// Get data into the corrsponding views
#Override
public void onBindViewHolder(RecipeAdapter.RecipeViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: " + position);
Recipe currentRecipe = mRecipes.get(position);
Log.d(TAG, "onBindViewHolder: setText " + currentRecipe);
holder.recipeTitleItemView.setText(currentRecipe.getTitle());
}
#Override
public int getItemCount() {
return mRecipes.size();
}
public void setRecipes(List<Recipe> recipes) {
this.mRecipes = recipes;
Log.d(TAG, "setRecipes: notifydataChanged" );
notifyDataSetChanged();
}
}
MainActivity:
package com.example.fillmyplate.activities;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.media.Image;
import android.os.Build;
import android.os.Bundle;
import com.example.fillmyplate.R;
import com.example.fillmyplate.entitys.Recipe;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.cardview.widget.CardView;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
public static final String TAG = "MainAcitivity";
private static final int NEW_RECIPE_ACTIVITY_REQUEST_CODE = 1;
private RecyclerView mRecyclerView;
private RecipeViewModel mRecipeViewmodel;
private RecyclerView.LayoutManager layoutManager;
//private final List<String> mTitleList = new LinkedList<>();
//NEU for adapter
private List<String> recipeDataList = new ArrayList<>();
RecipeRoomDatabase db;
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// RECYCLER VIEW STUFF
mRecyclerView = findViewById(R.id.recycler_view1);
mRecyclerView.setHasFixedSize(true);
// user linerar layout manager
layoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(layoutManager);
// specify an adapter
final RecipeAdapter recipeAdapter = new RecipeAdapter(this);
//mAdapter = new RecipeAdapter(this, mTitleList);
mRecyclerView.setAdapter(recipeAdapter);
mRecipeViewmodel = ViewModelProviders.of(this).get(RecipeViewModel.class);
mRecipeViewmodel.getAllRecipes().observe(this, new Observer<List<Recipe>>() {
#Override
public void onChanged(List<Recipe> recipes) {
Log.d(TAG, "onChanged: " + recipes.toString());
for (Recipe rec : recipes) {
Log.d(TAG, "onChanged: " + rec.getTitle());
Log.d(TAG, "onChanged: recipe id " + rec.getUid());
}
recipeAdapter.setRecipes(recipes);
}
});
// DB
db = Room.databaseBuilder(getApplicationContext(), RecipeRoomDatabase.class, "appdb").build();
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(MainActivity.this, AddRecipeActivity.class);
startActivityForResult(intent, NEW_RECIPE_ACTIVITY_REQUEST_CODE);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d(TAG, "onActivityResult: ");
if (requestCode == NEW_RECIPE_ACTIVITY_REQUEST_CODE && resultCode == RESULT_OK) {
Log.d(TAG, "onActivityResult: " + data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
// mTitleList.add(data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
Recipe rec = new Recipe(data.getStringExtra(AddRecipeActivity.EXTRA_REPLY));
mRecipeViewmodel.insert(rec);
} else {
Toast.makeText(
getApplicationContext(),
"saved",
Toast.LENGTH_LONG).show();
}
}
public void startKnownRecipeActivity(int position) {
Log.d(TAG, "startKnownRecipeActivity: Position " + position);
LiveData<List<Recipe>> recipe = mRecipeViewmodel.findById(position);
if (recipe.getValue().size() > 1) {
Log.d(TAG, "startKnownRecipeActivity: Error database found more than one recipe.");
} else {
Log.d(TAG, "startKnownRecipeActivity: Start activity with recipe " + recipe.getValue().get(0).getTitle());
}
}
}
The thing you need to do is to use a call back to send position back to activity.
To make sure that view position is correct you need to override 3 functions in RecyclerView Adapter:
#Override
public int getItemCount() {
return filteredUsers.size();
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public int getItemViewType(int position) {
return position;
}
For the Callback just create an Interface:
public interface AdapterListener {
void onClick(int id);
void onClick(ViewModel object);
}
Make a method in your Recycler Adapter:
private AdapterListener adapterListener;
public void setAdapterListener(AdapterListener mCallback) {
this.adapterListener = mCallback;
}
Implement this Interface on your Activity then you will get both methods of the interface.
public class MainActivity extends AppCompatActivity implements AdapterListener{
Register the listener by calling the setAdapterListener method in your activity after the initialization of the RecyclerView
adapterObject.setAdapterListener(MainActivity.this);
Then the last thing you need to do is call interface method in your item onClickListener, where u can either pass the complete model or just the id of the model
adapterListener.onClick(modelObject.getId());
OR
adapterListener.onClick(modelObject);
I'm trying to use Saripaar Validation on my project, but it's throwing the following error:
java.lang.IllegalStateException: No rules found. You must have at
least one rule to validate. If you are using custom annotations, make
sure that you have registered them using the 'Validator.register()'
method.
My architecture separates the responsibility for handling the view into a class, for example for LoginActivity I have LoginView, which is where I handle my view logic like ButterKnife injection, event listening, etc. In this class I have my annotated fields.My LoginView looks like this:
import android.content.res.ColorStateList;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.ImageViewCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.AppCompatEditText;
import android.text.method.HideReturnsTransformationMethod;
import android.text.method.PasswordTransformationMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
import com.mobsandgeeks.saripaar.ValidationError;
import com.mobsandgeeks.saripaar.Validator;
import com.mobsandgeeks.saripaar.annotation.Email;
import com.mobsandgeeks.saripaar.annotation.NotEmpty;
import com.mobsandgeeks.saripaar.annotation.Password;
import com.serti.android.feenicia.validatortest.R;
import com.serti.android.feenicia.validatortest.screen.login.LoginActivity;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import rx.Observable;
import rx.subjects.PublishSubject;
public class LoginView implements Validator.ValidationListener {
public static final String LOGIN_ACTION = "LOGIN";
#BindView(R.id.login_button)
Button loginButton;
#BindView(R.id.username_edittext)
#NotEmpty
#Email
AppCompatEditText usernameEditText;
#BindView(R.id.password_edittext)
#Password(min = 8, scheme = Password.Scheme.ALPHA_NUMERIC_MIXED_CASE_SYMBOLS)
AppCompatEditText passwordEditText;
#BindView(R.id.eye_imageview)
ImageView eyeImageView;
#BindView(R.id.loading_progressbar)
ProgressBar loadingProgressBar;
private boolean passwordIsVisible;
private AlertDialog confirmPaymentDialog;
private LoginActivity context;
private View rootView;
private PublishSubject<String> clickSubject = PublishSubject.create();
Validator validator;
public LoginView(LoginActivity context){
this.context = context;
FrameLayout parent = new FrameLayout(context);
parent.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
rootView = LayoutInflater.from(context).inflate(R.layout.activity_login, parent, true);
ButterKnife.bind(this, rootView);
validator = new Validator(context);
validator.setValidationListener(this);
eyeImageView.setOnClickListener(v -> handleClick(v.getId()));
loginButton.setOnClickListener(v -> handleClick(v.getId()));
passwordIsVisible = false;
}
#Override
public void onValidationSucceeded() {
String action = null;
Snackbar.make(rootView, "Validated", Snackbar.LENGTH_LONG).show();
loginButton.setVisibility(View.GONE);
loadingProgressBar.setVisibility(View.VISIBLE);
action = LOGIN_ACTION;
if(action != null){
clickSubject.onNext(action);
}
}
#Override
public void onValidationFailed(List<ValidationError> errors) {
for(ValidationError error : errors){
View view = error.getView();
String message = error.getCollatedErrorMessage(context);
if(view instanceof AppCompatEditText){
((AppCompatEditText) view).setError(message);
} else {
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
}
}
}
public String getUserName(){
return usernameEditText.getText().toString();
}
public String getPassword(){
return passwordEditText.getText().toString();
}
private void handleClick(int id){
String action = null;
switch (id){
case R.id.login_button:
validator.validate();
break;
case R.id.eye_imageview:
togglePasswordVisibility();
}
}
private void togglePasswordVisibility(){
int color = 0;
if(passwordIsVisible){
passwordEditText.setTransformationMethod(PasswordTransformationMethod.getInstance());
// eyeImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.eye_white));
color = ContextCompat.getColor(context, R.color.dark_blue_button);
ImageViewCompat.setImageTintList(eyeImageView, ColorStateList.valueOf(color));
}else{
passwordEditText.setTransformationMethod(HideReturnsTransformationMethod.getInstance());
// eyeImageView.setImageDrawable(context.getResources().getDrawable(R.drawable.eye_white));
color = ContextCompat.getColor(context, R.color.dark_gray);
}
ImageViewCompat.setImageTintList(eyeImageView, ColorStateList.valueOf(color));
passwordIsVisible = !passwordIsVisible;
passwordEditText.setSelection(passwordEditText.getText().length());
}
private void showIncompleteCredentialsMessage() {
Snackbar.make(loginButton, context.getText(R.string.incomplete_credentials_title), Snackbar.LENGTH_LONG).show();
}
public View getView(){
return rootView;
}
public Observable<String> observeClicks(){
return clickSubject;
}
public void openMainScreen(){
context.startMainActivity();
}
public void openSearchTicketsScreen() {
context.startSearchTicketsActivity();
}
public void showWrongCredentialsMessage() {
loginButton.setVisibility(View.VISIBLE);
loadingProgressBar.setVisibility(View.GONE);
Snackbar.make(loginButton, context.getText(R.string.wrong_credentials_title), Snackbar.LENGTH_LONG).show();
}
public void setContext(LoginActivity context) {
this.context = context;
}
}
From what I'm guessing, the library is trying to find these fields on my Activity, and since they're not there, then it's throwing this error.
Is there a way use this library accordingly to the architecture I'm handling?
use validator = new Validator(this) in place of validator = new Validator(context);
I'm working on a project that involves displaying a list of videos from the backend using retrofit, i want to display the video with some data on the UI using recyclerview, i'm trying to use TORO video library to handle the video but instead of displaying the video the video space is blank and black and other info apart the video was displayed successfully.
What i want is proper usage of the library if i'm getting it wrong, or link to other library that you have tested that i could use or how you do it in your own project if you have done it before.
check adapter code below used with the library.
package com.theproject.allClass.adapters;
import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.VideoView;
import com.bumptech.glide.Glide;
import com.google.android.exoplayer2.ui.SimpleExoPlayerView;
import com.klinker.android.simple_videoview.SimpleVideoView;
import com.theproject.R;
import com.theproject.allClass.api.model.AuditionRoom;
import com.theproject.allClass.api.model.Timeline;
import java.util.List;
import im.ene.toro.ToroPlayer;
import im.ene.toro.ToroUtil;
import im.ene.toro.exoplayer.SimpleExoPlayerViewHelper;
import im.ene.toro.media.PlaybackInfo;
import im.ene.toro.widget.Container;
public class AuditionRoomAdapter extends RecyclerView.Adapter<AuditionRoomAdapter.ViewHolder> {
private Context context;
private List<AuditionRoom> data;
public AuditionRoomAdapter(Context context, List<AuditionRoom> data) {
this.context = context;
this.data = data;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.audition_timeline, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.username.setText(data.get(position).getUsername());
holder.userPostText.setText(data.get(position).getUserMessage());
holder.yes.setText(""+data.get(position).getYes_votes_count());
holder.no.setText(""+data.get(position).getNo_votes_count());
Glide.with(context).load(data.get(position).getUserProfilepicUrl()).into(holder.userProfilePic);
// Glide.with(context).load(data.get(position).getUpload_file_url()).into(holder.userPostImage);
holder.bind(Uri.parse(data.get(position).getUpload_file_url()));
}
#Override
public int getItemCount() {
return data.size();
}
public class ViewHolder extends RecyclerView.ViewHolder implements ToroPlayer{
TextView username;
TextView userPostText;
TextView yes;
TextView no;
ImageView userProfilePic;
ImageView userPostImage;
SimpleExoPlayerView playerView;
SimpleExoPlayerViewHelper helper;
Uri mediaUri;
public ViewHolder(View itemView) {
super(itemView);
userProfilePic = itemView.findViewById(R.id.audition_user_profile_pic);
username = itemView.findViewById(R.id.audition_user_name);
userPostText = itemView.findViewById(R.id.audition_user_post_text);
//userPostImage = itemView.findViewById(R.id.audition_user_post_image);
playerView = itemView.findViewById(R.id.player);
yes = itemView.findViewById(R.id.audition_yes_figure);
no = itemView.findViewById(R.id.audition_no_figure);
}
#NonNull
#Override
public View getPlayerView() {
return playerView;
}
#NonNull
#Override
public PlaybackInfo getCurrentPlaybackInfo() {
return helper != null ? helper.getLatestPlaybackInfo() : new PlaybackInfo();
}
#Override
public void initialize(#NonNull Container container, #Nullable PlaybackInfo playbackInfo) {
if (helper == null) {
helper = new SimpleExoPlayerViewHelper(container, this, mediaUri);
}
helper.initialize(playbackInfo);
}
#Override
public void play() {
if (helper != null) helper.play();
}
#Override
public void pause() {
if (helper != null) helper.pause();
}
#Override
public boolean isPlaying() {
return helper != null && helper.isPlaying();
}
#Override
public void release() {
if (helper != null) {
helper.release();
helper = null;
}
}
#Override
public boolean wantsToPlay() {
return ToroUtil.visibleAreaOffset(this, itemView.getParent()) >= 0.85;
}
#Override
public int getPlayerOrder() {
return getAdapterPosition();
}
#Override
public void onSettled(Container container) {
}
// called from Adapter to setup the media
void bind(Uri item) {
if (item != null) {
mediaUri = item;
}
}
}
}
The result of the recyclerview with video not working
link to the library on github
https://github.com/eneim/toro/
i was able to solve the issue by adding the schema(http or https) to the loading url, TORO library is good for displaying video on a recyclerview, tested and confirmed.
I got same error but I resolved it by adding
Container instead of RecycerView.
<im.ene.toro.widget.Container android:id="#+id/recyleVideo" android:layout_width="match_parent" android:layout_height="match_parent" />
I have a RecyclerView and each item is a button. Each button will call the same activity by passing a different parameter to this activity.
I tried many solutions found on the web but none of them had worked for me.
Here is my adapter :
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import java.util.List;
public class FormAdapter extends RecyclerView.Adapter<FormAdapter.FormViewHolder> {
private List<Form> forms;
private int rowLayout;
private Context context;
public class FormViewHolder extends RecyclerView.ViewHolder {
LinearLayout formsLayout;
Button form;
public FormViewHolder(View v) {
super(v);
formsLayout = (LinearLayout) v.findViewById(R.id.forms_layout);
form = (Button) v.findViewById(R.id.formButton);
}
}
public FormAdapter(List<Form> forms, int rowLayout, Context context) {
this.forms = forms;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public FormAdapter.FormViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new FormViewHolder(view);
}
#Override
public void onBindViewHolder(FormViewHolder holder, final int position) {
holder.form.setText(forms.get(position).getSubject());
}
#Override
public int getItemCount() {
return forms.size();
}
}
A form is represented by the following class :
public class Form {
private final String subject;
private final int idForm;
public Form(String subject,int idForm)
{
this.idForm=idForm;
this.subject=subject;
}
public String getSubject()
{
return subject;
}
public int getIdForm()
{
return idForm;
}
}
And here is my MainActivity :
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private final static int idCreator = 1;
private FormAdapter formAdapter;
private List<Form> forms;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("Main activity");
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerViewForm);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
Formable formService =
ApiClient.getClient().create(Formable.class);
Call<List<Form>> call = formService.getForms(idCreator);
call.enqueue(new Callback<List<Form>>() {
#Override
public void onResponse(Call<List<Form>> call, Response<List<Form>> response) {
forms = response.body();
formAdapter=new FormAdapter(forms, R.layout.one_form, getApplicationContext());
recyclerView.setAdapter(formAdapter);
}
#Override
public void onFailure(Call<List<Form>> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
}
I have my buttons on screen but I don't understand how to make them call the activity "QuestionsActivity" with a parameter "idForm" that I know.
Here is the MainActivity when I run the app
Thanks in advance for your help
You can get item data by following way when you click on recyclerview item:
Create Interface in your adapter and use it in your activity:
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
Now Your code look like below:
FormAdapter.java
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import java.util.List;
public class FormAdapter extends RecyclerView.Adapter<FormAdapter.FormViewHolder> {
private List<Form> forms;
private int rowLayout;
private Context context;
private OnItemClickListener mListener;
public interface OnItemClickListener {
public void onItemClick(View view, int position);
}
public class FormViewHolder extends RecyclerView.ViewHolder {
LinearLayout formsLayout;
Button form;
public FormViewHolder(View v) {
super(v);
formsLayout = (LinearLayout) v.findViewById(R.id.forms_layout);
form = (Button) v.findViewById(R.id.formButton);
}
}
public FormAdapter(List<Form> forms, int rowLayout, Context context) {
this.forms = forms;
this.rowLayout = rowLayout;
this.context = context;
}
#Override
public FormAdapter.FormViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(rowLayout, parent, false);
return new FormViewHolder(view);
}
#Override
public void onBindViewHolder(FormViewHolder holder, final int position) {
holder.form.setText(forms.get(position).getSubject());
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if(mListener!=null)
{
mListener.onItemClick(view,position);
}
}
});
}
#Override
public int getItemCount() {
return forms.size();
}
public void setOnItemClick(OnItemClickListener listener)
{
this.mListener=listener;
}
}
MainActivity.java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import com.newstory.android.R;
import com.newstory.android.activity.FormAdapter;
import java.util.List;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private final static int idCreator = 1;
private FormAdapter formAdapter;
private List<Form> forms;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
setTitle("Main activity");
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerViewForm);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
Formable formService =
ApiClient.getClient().create(Formable.class);
Call<List<Form>> call = formService.getForms(idCreator);
call.enqueue(new Callback<List<Form>>() {
#Override
public void onResponse(Call<List<Form>> call, Response<List<Form>> response) {
forms = response.body();
formAdapter=new FormAdapter(forms, R.layout.one_form, getApplicationContext());
recyclerView.setAdapter(formAdapter);
setOnItemListener();
}
#Override
public void onFailure(Call<List<Form>> call, Throwable t) {
// Log error here since request failed
Log.e(TAG, t.toString());
}
});
}
public void setOnItemListener(){
if(formAdapter!=null)
{
formAdapter.setOnItemClick(new FormAdapter.OnItemClickListener() {
#Override
public void onItemClick(View view, int position) {
Form clickedForm=forms.get(position);
// You can call QuestionsActivity here
//Now you can access [Form] data
Log.d("getIdForm->",String.valueOf(clickedForm.getIdForm()))
}
});
}
}
}
I hope it's helps you.
Do this way :
form.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do something when the form is clicked
context.startActivity(new Intent(context, YourActivity.class)
.putExtra("idForm", someValue));
}
});
In your adapter's onBindViewHolder method, assign a click listener to the button view element, so it would look something like this:
#Override
public void onBindViewHolder(FormViewHolder holder, final int position {
holder.form.setText(forms.get(position).getSubject());
holder.form.setOnClickListener(v -> {
startQuestionsWithId(forms.get(position).getIdForm);
});
}
And then, your startQuestionsWithIdmethod would typically be like:
private void startQuestionsWithId(int idForm) {
Intent intent = new Intent(context, QuestionsActivity.class);
intent.putExtra("id_form", idForm);
context.startActivity(intent);
}
I have been reading the different answers here on stackoverflow and on this blog post and tried to implement their solutions but I am still getting the error: No adapter attached; skipping layout.
RecyclerAdapter:
package vn.jupviec.frontend.android.monitor.app.ui.candidate;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.w3c.dom.Text;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import butterknife.BindView;
import vn.jupviec.frontend.android.monitor.app.R;
import vn.jupviec.frontend.android.monitor.app.domain.candidate.TrainingDTO;
import vn.jupviec.frontend.android.monitor.app.util.Utils;
/**
* Created by Windows 10 Gamer on 16/12/2016.
*/
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> {
private static final String TAG = "RecyclerView";
private List<TrainingDTO> mTrainingDTOs;
private Context mContext;
private LayoutInflater mLayoutInflater;
private String today;
private static final DateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
AdapterInterface buttonListener;
public RecyclerAdapter(Context context, List<TrainingDTO> datas, AdapterInterface buttonListener) {
mContext = context;
mTrainingDTOs = datas;
this.mLayoutInflater = LayoutInflater.from(mContext);
this.buttonListener = buttonListener;
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.candidate_item, parent, false);
// View itemView = mLayoutInflater.inflate(R.layout.candidate_item, parent, false);
return new RecyclerViewHolder(itemView);
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
final ObjectMapper mapper = new ObjectMapper();
final TrainingDTO trainingDTO = mapper.convertValue(mTrainingDTOs.get(position), TrainingDTO.class);
holder.tvName.setText(trainingDTO.getMaidName());
holder.status.setVisibility(View.GONE);
Date date = new Date();
String currentDate = sdf.format(date);
for (TrainingDTO.TrainingDetailDto td : trainingDTO.getListTrain()) {
today = Utils.formatDate((long) td.getTrainingDate(),"dd/MM/yyyy");
break;
}
if(currentDate.equals(today)) {
holder.status.setVisibility(View.VISIBLE);
holder.status.setText("(Mới)");
}
holder.btnHistory.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(mContext,R.string.msg_no_candidate_history,Toast.LENGTH_SHORT).show();
}
});
holder.btnTest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonListener.showComment(trainingDTO);
}
});
}
#Override
public int getItemCount() {
int size ;
if(mTrainingDTOs != null && !mTrainingDTOs.isEmpty()) {
size = mTrainingDTOs.size();
}
else {
size = 0;
}
return size;
}
class RecyclerViewHolder extends RecyclerView.ViewHolder {
private TextView tvName;
private Button btnTest;
private Button btnHistory;
private TextView status;
public RecyclerViewHolder(View itemView) {
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.txtName);
btnTest = (Button) itemView.findViewById(R.id.btnTest);
btnHistory = (Button) itemView.findViewById(R.id.btnHistory);
status = (TextView)itemView.findViewById(R.id.status);
}
}
public boolean removeItem(int position) {
if (mTrainingDTOs.size() >= position + 1) {
mTrainingDTOs.remove(position);
return true;
}
return false;
}
public interface AdapterInterface {
void showComment(TrainingDTO trainingDTO);
void showHistory(TrainingDTO trainingDTO);
}
}
FragmentTapNew:
package vn.jupviec.frontend.android.monitor.app.ui.candidate;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.drawable.ClipDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.RoundRectShape;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.Unbinder;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
import vn.jupviec.frontend.android.monitor.app.R;
import vn.jupviec.frontend.android.monitor.app.domain.ResultDTO;
import vn.jupviec.frontend.android.monitor.app.domain.candidate.TrainingDTO;
import vn.jupviec.frontend.android.monitor.app.domain.training.CandidateService;
import vn.jupviec.frontend.android.monitor.app.util.Constants;
import vn.jupviec.frontend.android.monitor.app.util.Utils;
/**
* Created by Windows 10 Gamer on 09/12/2016.
*/
public class FragmentTapNew extends Fragment implements RecyclerAdapter.AdapterInterface {
private static final String TAG = FragmentTapNew.class.getSimpleName();
Activity myContext = null;
private OnItemSelectedListener listener;
ShapeDrawable shapeDrawable;
#BindView(R.id.lvToday)
RecyclerView lvToday;
#BindView(R.id.textView)
TextView textView;
#BindView(R.id.pb_loading)
ProgressBar pbLoading;
private Unbinder unbinder;
private boolean loading = true;
int pastVisiblesItems, visibleItemCount, totalItemCount;
ArrayList<TrainingDTO> mTrainingDTO ;
RecyclerAdapter mTrainingDTOAdapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.activity_candidate_training, container, false);
unbinder = ButterKnife.bind(this, v);
initViews();
return v;
}
private void initViews() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
lvToday.setHasFixedSize(true);
lvToday.setNestedScrollingEnabled(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
today();
}
});
t.start();
}
private boolean isNetworkConnected() {
ConnectivityManager cm = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni == null) {
Toast.makeText(getActivity(), R.string.err_cannot_establish_connection, Toast.LENGTH_SHORT).show();
return false;
} else
return true;
}
private void today() {
if(isNetworkConnected()){
String token = "a";
Integer date = 0;
setLoadingVisible(true);
CandidateService.getApiDummyClient(getContext()).getCandidate(
token,
date,
Constants.TRAINING,
Arrays.asList(Constants.TRAINING_DAY_NEW),
new Callback<ResultDTO>() {
#Override
public void success(ResultDTO resultDTO, Response response) {
setLoadingVisible(false);
mTrainingDTO = (ArrayList<TrainingDTO>) resultDTO.getData();
if (mTrainingDTO.size() == 0) {
if(textView!=null) {
textView.setVisibility(View.VISIBLE);
textView.setTextColor(Color.RED);
textView.setGravity(Gravity.CENTER | Gravity.BOTTOM);
}
} else {
if(textView!=null) {
textView.setVisibility(View.GONE);
}
if(null==mTrainingDTOAdapter) {
mTrainingDTOAdapter = new RecyclerAdapter(getActivity(), mTrainingDTO, FragmentTapNew.this);
lvToday.setAdapter(mTrainingDTOAdapter);
} else {
lvToday.setAdapter(mTrainingDTOAdapter);
mTrainingDTOAdapter.notifyDataSetChanged();
}
lvToday.invalidate();
}
}
#Override
public void failure(RetrofitError error) {
Log.e(TAG, "JV-ERROR: " + error.getMessage());
Log.e(TAG, "JV-ERROR: " + error.getSuccessType());
}
});
}
}
#Override
public void onResume() {
setLoadingVisible(false);
initViews();
lvToday.setAdapter(mTrainingDTOAdapter);
super.onResume();
}
#Override
public void onDestroyView() {
super.onDestroyView();
unbinder.unbind();
}
private void setLoadingVisible(boolean visible) {
// pbLoading.getIndeterminateDrawable().setColorFilter(0xFFFF0000, android.graphics.PorterDuff.Mode.MULTIPLY);
if(pbLoading!=null) {
pbLoading.setVisibility(visible ? View.VISIBLE : View.GONE);
lvToday.setVisibility(visible ? View.GONE : View.VISIBLE);
}
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
if (activity instanceof OnItemSelectedListener) {
listener = (OnItemSelectedListener) activity;
} else {
throw new ClassCastException(activity.toString()
+ " phải implemenet MyListFragment.OnItemSelectedListener");
}
}
#Override
public void onDetach() {
super.onDetach();
listener = null;
}
#Override
public void showComment(TrainingDTO trainingDTO) {
Intent intent = new Intent(getContext(), CommentActivity.class);
intent.putExtra(Constants.ARG_NAME_DETAIL, trainingDTO);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
}
#Override
public void showHistory(TrainingDTO trainingDTO) {
Intent intent = new Intent(getContext(), HistoryActivity.class);
intent.putExtra(Constants.ARG_CANDIDATE_HISTORY_DETAIL, trainingDTO);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
getContext().startActivity(intent);
}
public interface OnItemSelectedListener {
void showComment(TrainingDTO trainingDTO);
void showHistory(TrainingDTO trainingDTO);
}
}
The first, you don't need to set adapter multiple time, only set adapter at the first time in your method initView().
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
lvToday.setHasFixedSize(true);
lvToday.setNestedScrollingEnabled(false);
if(mTrainingDTO == null) {
mTrainingDTO = new ArrayList<>();
}
if(null == mTrainingDTOAdapter ) {
mTrainingDTOAdapter = new RecyclerAdapter(getActivity(), mTrainingDTO, FragmentTapNew.this);
}
lvToday.setAdapter(mTrainingDTOAdapter);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
today();
}
});
t.start();
After that, you don't need to call lvToday.setAdapter(mTrainingDTOAdapter);
many times. Just call mTrainingDTOAdapter.notifyDataSetChanged(); if having any changes in your data mTrainingDTO.
The errorlog - error:No adapter attached; skipping layout indicates that you've attached LayoutManager but you haven't attached an adapter yet, so recyclerview will skip layout. I'm not sure but, in other words recyclerView will skip layout measuring at the moment.
to prevent this errorLog Try to set an adapter with an empty dataSet i.e. ArrayList or
Attach LayoutManager just before you are setting your adapter.
Try this,
private void initViews() {
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
LinearLayoutManager mLinearLayoutManager = new LinearLayoutManager(getActivity());
lvToday.setLayoutManager(mLinearLayoutManager);
lvToday.setHasFixedSize(true);
lvToday.setNestedScrollingEnabled(false);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
today();
}
});
t.start();
}