darth_daniel
Lurker
Hi,
I am building an android tv app with a BrowseFragment that displays a listrow with data pulled from a php created JSON file (data is got from MySQL table). There is a check that is run to see if any changes to the database and after which when the change is detected, the BrowseFragment is to be refreshed reloading the json data.
I attempted the refresh from both the BrowseFragments parent activity and the fragment itself (I attempted to use the clear() and addall() functions of ArrayObjectAdapter) and there would just be a flash/blinking but the information would not be refreshed. The only way I have been able to update the listrow has been to restart the app.
How can I successfully update/refresh the BrowseFragment list row?
I have placed the code for my MainFragment and BrowseFragment
I am building an android tv app with a BrowseFragment that displays a listrow with data pulled from a php created JSON file (data is got from MySQL table). There is a check that is run to see if any changes to the database and after which when the change is detected, the BrowseFragment is to be refreshed reloading the json data.
I attempted the refresh from both the BrowseFragments parent activity and the fragment itself (I attempted to use the clear() and addall() functions of ArrayObjectAdapter) and there would just be a flash/blinking but the information would not be refreshed. The only way I have been able to update the listrow has been to restart the app.
How can I successfully update/refresh the BrowseFragment list row?
I have placed the code for my MainFragment and BrowseFragment
Java:
public class MainFragment extends BrowseSupportFragment
implements LoaderManager.LoaderCallbacks<LinkedHashMap<String, List<Video>>>{
private static final int BACKGROUND_UPDATE_DELAY = 300;
private static final String TAG = MainFragment.class.getSimpleName();
static final int GRID_ITEM_WIDTH = 300;
private static final int GRID_ITEM_HEIGHT = 200;
private final Handler mHandler = new Handler();
//private ArrayObjectAdapter mRowsAdapter;
private CustumArrayObjectAdapter mRowsAdapter;
private Drawable mDefaultBackground;
private DisplayMetrics mMetrics;
private Runnable mBackgroundTask;
private Uri mBackgroundURI;
private BackgroundManager mBackgroundManager;
private CustomListRow mGridItemListRow;
private LoaderManager mLoaderManager;
ArrayList<Video> mItems = null;
private ArrayList<CustomListRow> mVideoListRowArray;
private static final int VIDEO_ITEM_LOADER_ID = 1;
/**
// Init
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
updateChannels();
handler.postDelayed(this, 10000);
}
};
**/
@Override
public void onActivityCreated(Bundle savedInstanceState) {
// Final initialization, modifying UI elements.
super.onActivityCreated(savedInstanceState);
// Prepare the manager that maintains the same background image between activities.
prepareBackgroundManager();
setupUIElements();
loadRows();
setRows();
mBackgroundURI = Uri.parse("http://192.168.0.4/test/images/bkground/background1.jpg");
;
mLoaderManager = LoaderManager.getInstance(this);
mLoaderManager.initLoader(VIDEO_ITEM_LOADER_ID, null, this);
setupEventListeners();
prepareEntranceTransition();
updateRecommendations();
/**
//Start
handler.postDelayed(runnable, 10000);
**/
}
@Override
public void onDestroy() {
mHandler.removeCallbacks(mBackgroundTask);
mBackgroundManager = null;
super.onDestroy();
}
/**
public void updateChannels(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.JSONURL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
ApiInterface api = retrofit.create(ApiInterface.class);
Call<String> call = api.getString();
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i("Responsestring", response.body().toString());
//Toast.makeText()
if (response.isSuccessful()) {
if (response.body() != null) {
Log.i("onSuccess", response.body().toString());
String jsonresponse = response.body().toString();
chkResponse(jsonresponse);
} else {
Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
private void chkResponse(String response){
try {
//getting the whole json object from the response
JSONObject obj = new JSONObject(response);
if(obj.optString("update").equals("true"))
{
try {
getLoaderManager().restartLoader(0, null, this);
mVideoListRowArray = null;
mItems = null;
mLoaderManager.restartLoader(0, null, this);
mLoaderManager = LoaderManager.getInstance(this);
mLoaderManager.initLoader(VIDEO_ITEM_LOADER_ID, null, this);
setupUIElements();
loadRows();
setRows();
mRowsAdapter.clear();
mRowsAdapter.addAll(0, mVideoListRowArray);
mRowsAdapter.replaceAll(0, mVideoListRowArray);
//Intent intent = new Intent(getActivity(), MainActivity.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
//startActivity(intent);
} catch (Exception e)
{
Toast.makeText(this, "Error Refreshing Channel Rows.", Toast.LENGTH_SHORT).show();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
**/
/**
@Override
public void onResume() {
mCategoryRowAdapter.clear();
mLoaderManager = LoaderManager.getInstance(this);
mLoaderManager.initLoader(CATEGORY_LOADER, null, this);
mCategoryRowAdapter = new ArrayObjectAdapter(new ListRowPresenter());
setAdapter(mCategoryRowAdapter);
super.onResume();
}
**/
@Override
public void onStop() {
mBackgroundManager.release();
super.onStop();
}
private void prepareBackgroundManager() {
mBackgroundManager = BackgroundManager.getInstance(getActivity());
mBackgroundManager.attach(getActivity().getWindow());
mDefaultBackground = getResources().getDrawable(R.drawable.backgroundtv, null);
mBackgroundTask = new UpdateBackgroundTask();
mMetrics = new DisplayMetrics();
getActivity().getWindowManager().getDefaultDisplay().getMetrics(mMetrics);
}
private void setupUIElements() {
setBadgeDrawable(
getActivity().getResources().getDrawable(R.drawable.twende, null));
setTitle(getString(R.string.browse_title)); // Badge, when set, takes precedent over title
setHeadersState(HEADERS_ENABLED);
setHeadersTransitionOnBackEnabled(true);
// Set fastLane (or headers) background color
setBrandColor(ContextCompat.getColor(getActivity(), R.color.fastlane_background));
// Set search icon color.
setSearchAffordanceColor(ContextCompat.getColor(getActivity(), R.color.search_opaque));
setHeaderPresenterSelector(new PresenterSelector() {
@Override
public Presenter getPresenter(Object o) {
return new IconHeaderItemPresenter();
}
});
}
private void setupEventListeners() {
setOnSearchClickedListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Intent intent = new Intent(getActivity(), SearchActivity.class);
//startActivity(intent);
}
});
setOnItemViewClickedListener(new ItemViewClickedListener());
setOnItemViewSelectedListener(new ItemViewSelectedListener());
}
private void updateBackground(String uri) {
int width = mMetrics.widthPixels;
int height = mMetrics.heightPixels;
RequestOptions options = new RequestOptions()
.centerCrop()
.error(mDefaultBackground);
Glide.with(getActivity())
.asBitmap()
.load(uri)
.apply(options)
.into(new SimpleTarget<Bitmap>(width, height) {
@Override
public void onResourceReady(
Bitmap resource,
Transition<? super Bitmap> transition) {
mBackgroundManager.setBitmap(resource);
}
});
}
private void startBackgroundTimer() {
mHandler.removeCallbacks(mBackgroundTask);
mHandler.postDelayed(mBackgroundTask, BACKGROUND_UPDATE_DELAY);
}
private void updateRecommendations() {
Intent recommendationIntent = new Intent(getActivity(), UpdateRecommendationsService.class);
getActivity().startService(recommendationIntent);
}
private class UpdateBackgroundTask implements Runnable {
@Override
public void run() {
if (mBackgroundURI != null) {
updateBackground(mBackgroundURI.toString());
}
}
}
private final class ItemViewClickedListener implements OnItemViewClickedListener {
@Override
public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
RowPresenter.ViewHolder rowViewHolder, Row row) {
if (item instanceof Video) {
Video video = (Video) item;
Intent intent = new Intent(getActivity(), VideoDetailsActivity.class);
intent.putExtra(VideoDetailsActivity.VIDEO, video);
Bundle bundle = ActivityOptionsCompat.makeSceneTransitionAnimation(
getActivity(),
((ImageCardView) itemViewHolder.view).getMainImageView(),
VideoDetailsActivity.SHARED_ELEMENT_NAME).toBundle();
getActivity().startActivity(intent, bundle);
} else if (item instanceof String) {
if (((String) item).contains(getString(R.string.guidedstep_first_title))) {
Intent intent = new Intent(getActivity(), GuidedStepActivity.class);
Bundle bundle =
ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity())
.toBundle();
startActivity(intent, bundle);
} else if (((String) item).contains(getString(R.string.error_fragment))) {
BrowseErrorFragment errorFragment = new BrowseErrorFragment();
getFragmentManager().beginTransaction().replace(R.id.movie_frame, errorFragment)
.addToBackStack(null).commit();
} else if(((String) item).contains(getString(R.string.personal_settings))) {
Intent intent = new Intent(getActivity(), SettingsActivity.class);
Bundle bundle =
ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity())
.toBundle();
startActivity(intent, bundle);
} else {
Toast.makeText(getActivity(), ((String) item), Toast.LENGTH_SHORT)
.show();
}
}
}
}
private void loadRows() {
/* GridItemPresenter */
IconHeaderItem gridItemPresenterHeader = new IconHeaderItem(0, "More", R.drawable.tv_animation_d);
GridItemPresenter mGridPresenter = new GridItemPresenter();
ArrayObjectAdapter gridRowAdapter = new ArrayObjectAdapter(mGridPresenter);
/**
gridRowAdapter.add(GRID_STRING_EXIT);
gridRowAdapter.add(GRID_STRING_VIDEOS);
gridRowAdapter.add(GRID_STRING_VERTICAL_GRID_FRAGMENT);
gridRowAdapter.add(GRID_STRING_RECOMMENDATION);
gridRowAdapter.add(GRID_STRING_SPINNER);
**/
mGridItemListRow = new CustomListRow(gridItemPresenterHeader, gridRowAdapter);
}
private void setRows() {
mRowsAdapter = new CustumArrayObjectAdapter(new CustomListRowPresenter()); // Initialize
if(mVideoListRowArray != null) {
for (CustomListRow videoListRow : mVideoListRowArray) {
mRowsAdapter.add(videoListRow);
}
}
if(mGridItemListRow != null) {
mRowsAdapter.add(mGridItemListRow);
}
/* Set */
setAdapter(mRowsAdapter);
}
@Override
public Loader<LinkedHashMap<String, List<Video>>> onCreateLoader(int id, Bundle args) {
/* Create new Loader */
Log.d(TAG, "onCreateLoader");
if(id == VIDEO_ITEM_LOADER_ID) {
Log.d(TAG, "create VideoItemLoader");
//return new VideoItemLoader(getActivity());
return new TvItemLoader(getActivity().getApplicationContext());
}
return null;
}
@Override
public void onLoadFinished(Loader<LinkedHashMap<String, List<Video>>> loader, LinkedHashMap<String, List<Video>> data) {
Log.d(TAG, "onLoadFinished");
/* Loader data has prepared. Start updating UI here */
switch (loader.getId()) {
case VIDEO_ITEM_LOADER_ID:
Log.d(TAG, "VideoLists UI update");
/* Hold data reference to use it for recommendation */
mItems = new ArrayList<Video>();
/* loadRows: videoListRow - CardPresenter */
int index = 1;
mVideoListRowArray = new ArrayList<>();
TvCardPresenter cardPresenter = new TvCardPresenter();
if (null != data) {
for (Map.Entry<String, List<Video>> entry : data.entrySet()) {
ArrayObjectAdapter cardRowAdapter = new ArrayObjectAdapter(cardPresenter);
List<Video> list = entry.getValue();
for (int j = 0; j < list.size(); j++) {
Video movie = list.get(j);
cardRowAdapter.add(movie);
mItems.add(movie); // Add movie reference for recommendation purpose.
}
IconHeaderItem header = new IconHeaderItem(index, entry.getKey(), R.drawable.tv_animation_d);
index++;
CustomListRow videoListRow = new CustomListRow(header, cardRowAdapter);
videoListRow.setNumRows(1);
mVideoListRowArray.add(videoListRow);
}
} else {
Log.e(TAG, "An error occurred fetching videos");
}
/* Set */
setRows();
}
}
@Override
public void onLoaderReset(Loader<LinkedHashMap<String, List<Video>>> loader) {
Log.d(TAG, "onLoadReset");
/* When it is called, Loader data is now unavailable due to some reason. */
}
private class GridItemPresenter extends Presenter {
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent) {
TextView view = new TextView(parent.getContext());
view.setLayoutParams(new ViewGroup.LayoutParams(GRID_ITEM_WIDTH, GRID_ITEM_HEIGHT));
view.setFocusable(true);
view.setFocusableInTouchMode(true);
view.setBackgroundColor(getResources().getColor(R.color.default_background));
view.setTextColor(Color.WHITE);
view.setGravity(Gravity.CENTER);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, Object item) {
((TextView) viewHolder.view).setText((String) item);
}
@Override
public void onUnbindViewHolder(ViewHolder viewHolder) {
}
}
private final class ItemViewSelectedListener implements OnItemViewSelectedListener {
@Override
public void onItemSelected(Presenter.ViewHolder itemViewHolder, Object item,
RowPresenter.ViewHolder rowViewHolder, Row row) {
// each time the item is selected, code inside here will be executed.
if (item instanceof String) { // GridItemPresenter
startBackgroundTimer();
} else if (item instanceof Video) { // CardPresenter
startBackgroundTimer();
}
}
}
}
Java:
public class MainActivity extends LeanbackActivity {
// Init
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
@Override
public void run() {
updateChannels();
handler.postDelayed(this, 10000);
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
handler.postDelayed(runnable, 10000);
}
public void updateChannels(){
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(ApiInterface.JSONURL)
.addConverterFactory(ScalarsConverterFactory.create())
.build();
ApiInterface api = retrofit.create(ApiInterface.class);
Call<String> call = api.getString();
call.enqueue(new Callback<String>() {
@Override
public void onResponse(Call<String> call, Response<String> response) {
Log.i("Responsestring", response.body().toString());
//Toast.makeText()
if (response.isSuccessful()) {
if (response.body() != null) {
Log.i("onSuccess", response.body().toString());
String jsonresponse = response.body().toString();
chkResponse(jsonresponse);
} else {
Log.i("onEmptyResponse", "Returned empty response");//Toast.makeText(getContext(),"Nothing returned",Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onFailure(Call<String> call, Throwable t) {
}
});
}
private void chkResponse(String response){
try {
//getting the whole json object from the response
JSONObject obj = new JSONObject(response);
if(obj.optString("update").equals("true"))
{
try {
Intent i = new Intent(MainActivity.this, MainFragment.class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
} catch (Exception e)
{
Toast.makeText(this, "Error Refreshing Channel Rows.", Toast.LENGTH_SHORT).show();
}
}
} catch (JSONException e) {
e.printStackTrace();
}
}
}