cannot create a new Fragment in custom FragmentStatePagerAdapter - android

I'm trying to pre-populate a FragmentStatePagerAdapter with a list of objects but I cannot instantiate a new fragment.
Background:
My PagerAdapter consists of an ArrayList of Msg objects (mMsgConvoList).
MsgConvoList is an ArrayList of all messages from a given thread.
The partitioning of mMsgConvoList creates sublists of 3 msgs each (msgSublist).
Each sublist is put through the while loop to be handled by the PagerAdapter in creating new fragments, and adding additional textviews:
How the logic in the while loop works:
If the count == 2, that means there should be a new fragment, otherwise if the count is 1 to 0, locate the currentFragment and add the Msg (this is where the error occurs).
Error:
The error is occurring after the count == 2. The currentFragment is NULL on the 'else' portion of the while loop (count = 1 or 0). It seems like instantiateItem on the MsgFragment is never called. I'm not sure why this doesn't work when using the loop below.
Caused by: java.lang.NullPointerException
at to.testing.viewpagertest.MsgPagerActivity.onCreate(MsgPagerActivity.java:55)
If I remove the all the code within the 'else' condition from while loop, the fragment is created and the object is added to the text view:
if (count == 2){
mAdapter.addMessages(msgSublist.get(count));
mAdapter.notifyDataSetChanged();
mViewPager.setCurrentItem(mAdapter.getCount(), true);
This tells me a few things: The above code, outside of the while loop works, so the dataset is working correctly inside the textView and the fragment is being created successfully. It is only when I try to add an additional Msg object to the existing Array, that the currentFragment never seems to get created. Any suggestions would be much appreciated.
MsgPagerActivity:
if(mMsgConvoList.size() > 0) {
List msgPartitions = daoMsg.partitionArray(mMsgConvoList, 3);
mAdapter = new CustomPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mAdapter);
for(int i = msgPartitions.size() - 1; i >= 0; i--){
//extract msg objects from each sublist
List<Msg> msgSublist = (List<Msg>)msgPartitions.get(i);
int count = msgSublist.size() -1;
while(count >= 0){
if (count == 2){
mAdapter.addMessages(msgSublist.get(count));
mAdapter.notifyDataSetChanged();
mViewPager.setCurrentItem(mAdapter.getCount(), true);
}else{
mViewPager.setCurrentItem(mAdapter.getCount(), true);
MsgFragment currentFragment = (MsgFragment)mAdapter.getFragmentAtPosition(
mAdapter.getCount() - 1);
currentFragment.addMessage(msgSublist.get(count));
}
count--;
}

Related

Android Studio - App crash when using intent parameter

I have a function that 'crafts' products using two String parameters.
This is working fine when I put in hard coded strings like 'Wheel' & 'Car'.
But it makes my application crash if I try to put in the exact same strings but then provided by an intent.
I already tried to give in variable into the intent instead of a hard coded string. That did not work either.
Here is some part of the code. EDIT: Error log now included
productLeft = getIntent().getStringExtra("PRODUCT LEFT");
productRight = getIntent().getStringExtra("PRODUCT RIGHT");
public void craft(String product1, String product2) {
String[][] Products = factory.getProductList();
int i = 0;
while (finalProduct == "") {
int j;
for(j = 0; j < 3; j++){
if (product1 == Products[i][0] || product2 == Products[i][0]) {
if (product1 == Products[i][1] || product2 == Products[i][1]){
finalProduct = Products[i][2];
}
}
i++;
}
}
}
Problem is with the array index obviously. The array has only four elements and you are fetching index 4, probably in for loop with i variable. But then again I also do not see the role of j in that loop, can't tell without other parts of code.

Adding int to arraylist only if it does not already exist

I have position that is equal to which question is shown. I want to add an int equal to position to an arraylist. Then I want to check and see if that arraylist has that int within it to prevent that int being added again. With the following code it adds the position int multiple times.
if(correctQuestions.size() == 0){
correctQuestions.add(position);
}else if(correctQuestions.size() > 0){
if(!Arrays.asList(correctQuestions).contains(position)){
correctQuestions.add(position);
}
}
If position = 0; then each run of this code will continually add position to my arraylist regardless if 0 is in it or not. For instance running this code 3 times will result in my arraylist outputting [0,0,0] when it should only allow it to add 0 once.
you must write like this:
if(correctQuestions.size() == 0){
correctQuestions.add(position);
}else if(correctQuestions.size() > 0){
if(!correctQuestions.contains(position)){
correctQuestions.add(position);
}
}
try this :
if(correctQuestions.indexOf(position) < 0) {//this will return -1 if object not found in the arraylist
correctQuestions.add(position);
}
You will have maximum index of your Arraylist assume it as variable size.
So you can write conditional logic :
if(size!=0 && position < size ){
correctQuestions.add(position);
}
The method arrayList.size() returns the number of items in the list - so if the index is greater than or equal to the size(), it doesn't exist.
if(correctQuestions.size() > position){
correctQuestions.add(position);
}
if you want to check if position already present in arraylist if `correctQuestions.get( index );` in try block shows that if no key present it will throw in catch
try {
correctQuestions.get( index );
} catch ( IndexOutOfBoundsException e ) {
correctQuestions.add( index, new Object() );
}

Android - Load more data using AsyncTask which gets data from API in RecyclerView

I'm trying to dynamically add items to my RecyclerView.
Basically, I am following Instagram style, especially in the search fragment of Instagram. Currently, my app gets the number of item sent by server (default is 10) and add it onto the number of displayed items on the recyclerview.
I have an interface to get the output from the server, here's the OnLoadMoreListener
System.out.println("OnLoadMore");
list.add(null);
profilTemanAdapter.notifyItemInserted(list.size());
handler.postDelayed(new Runnable() {
#Override
public void run() {
//remove progress item
list.remove(list.size() - 1);
profilTemanAdapter.notifyItemRemoved(list.size());
TimelineFriendListAPI timelineFriendListAPIInput = new TimelineFriendListAPI();
timelineFriendListAPIInput.kevin.query.user_id = userId;
timelineFriendListAPIInput.kevin.query.other_user_id = otherUserId;
timelineFriendListAPIInput.kevin.query.friend_mode = friendMode;
nextFriendList = result.kevin.results.friend_list;
TimelineFriendListAPIFunc timelineFriendListAPIFunc = new TimelineFriendListAPIFunc(BottomProfilTemanFragment.this.getActivity());
timelineFriendListAPIFunc.delegate = BottomProfilTemanFragment.this;
if (nextFriendList.size() == 10) {
counter += 10;
timelineFriendListAPIInput.kevin.query.friend_count = String.valueOf(counter);
Log.d("CounterBefore", String.valueOf(counter));
timelineFriendListAPIFunc.execute(timelineFriendListAPIInput);
Log.d("CounterAfter", String.valueOf(counter));
Log.d("FriendLists", nextFriendList.get(0).friend_alias);
//Refresh Per Item
for (int i = 0; i < 10; i++) {
list.add(nextFriendList.get(i));
profilTemanAdapter.notifyItemInserted(list.size());
Log.d("FriendLists", nextFriendList.get(i).friend_alias);
}
Log.d("FriendLists", nextFriendList.get(10).friend_alias);
Log.d("OnLoadNotifFriendSize10", "size = " + list.size());
profilTemanAdapter.setLoaded();
} else if (nextFriendList.size() < 10 && nextFriendList.size() > 0) {
int friendCounter = nextFriendList.size();
counter += friendCounter;
timelineFriendListAPIInput.kevin.query.friend_count = String.valueOf(counter);
timelineFriendListAPIFunc.execute(timelineFriendListAPIInput);
//Refresh Per Item
for (int i = 0; i < friendCounter; i++) {
list.add(nextFriendList.get(i));
}
profilTemanAdapter.notifyItemInserted(list.size());
profilTemanAdapter.setLoaded();
} else {
}
}
}, 1000);
System.out.println("loadMore");
Here's the Interface function in the same class
result = output; //result is a global variable to be accessed inside the OnLoadMore
//profilTemanAdapter = new ProfilTemanAdapter(list, recyclerView, output);
//createlist();
handler = new Handler();
list = output.kevin.results.friend_list;profilTemanAdapter = new `ProfilTemanAdapter(list, recyclerView, output);`
profilTemanAdapter.setOnLoadMoreListener(profilTemanAdapterHandler);
recyclerView.setAdapter(profilTemanAdapter);
Log.d("FriendLists", list.get(0).friend_alias);
As can be expected, nextFriendList.get(10).friend_alias which is the 11th value in the List, is still the same as nextFriendList.get(0).friend_alias as nextFriendList has not been updated through the interface.
How to display it correctly as in waiting for the AsyncTask to finish, but not using .get() so that it doesn't block UI thread just like Instagram (or any "InfiniteScrolling" app) ?
Small update :
Used ProgressBar in Async so that it loads the information gained from server before displaying, but it messed the layout. There's an EditText above the RecyclerView which gets repeated on every OnLoadMore. Moreover it doesn't look nice with ProgressBar popping up for every information load..
Another update :
I am able to display OnLoadMore items but it replaces the items before the new items.

Cursor is looping but repeats only the first value

I created a loop that will get the data from my cursor, however I noticed that even though it is looping(with the correct count) it only shows the first value.
int vv = 0;
if ((CR3.moveToFirst()) || CR3.getCount() !=0){
while (CR3.isAfterLast() == false) {
vendoName[vv] = CR3.getString(0);
vendoEsch[vv] = CR3.getString(1);
vendoAsch[vv] = CR3.getString(2);
vendoTag[vv] = CR3.getString(3);
vv++;
CR3.moveToNext();
}}
and when I call all my data( I only need the first three records)
ArrayList<SearchResults2> results2 = new ArrayList<SearchResults2>();
SearchResults2 sr2 = new SearchResults2();
for(int j = 0;j < 3;j++)
{
sr2.setName(vendoName[j]);
sr2.setEsch(vendoEsch[j]);
sr2.setAsch(vendoAsch[j]);
sr2.setTag(vendoTag[j]);
results2.add(sr2);
}
I am putting inside a listview, when I check, it is showing always the first data.
This is an example I used as a reference to my code(It's almost the same except that I used an array to put my data from)
http://geekswithblogs.net/bosuch/archive/2011/01/31/android---create-a-custom-multi-line-listview-bound-to-an.aspx
Am I doing something wrong which is why it is only getting the first piece of data?
Is it not easier to do something like this (if you don't need more than 3 results):
ArrayList<SearchResults2> results2 = new ArrayList<SearchResults2>();
CR3.moveToFirst();
for (i = 0; i < 3; i++) {
SearchResults2 sr2 = new SearchResults2();
sr2.setName(CR3.getString(0));
sr2.setEsch(CR3.getString(1));
sr2.setAsch(CR3.getString(2));
sr2.setTag(CR3.getString(3));
results2.add(sr2);
CR3.moveToNext();
}
I think that maybe the cursor doesn't iterate properly through your results in your while-loop and that's why you become one and the same result for the three items

Fragment not added to activity when method is called

I have a main activity called Chessboard. Within Chessboard, in the onCreate, I set a fragment activity GameInfoFragment. After this, a call is made to query an SQLite database, immediately after which a method in class SQLiteDataInterpreter is called. From here, a call is made to a method in the GameInfoFragment class, where imageViews in the fragment I set in Chessboard's onCreate should be populated.
When I attempt to start the Chessboard activity, I receive the following error:
Caused by: java.lang.IllegalStateException: Fragment GameInfoFragment{2ef389d9 id=0x7f09008d InfoTest} not attached to Activity
The code in Chessboard's onCreate is the following:
FragmentManager manager = this.getFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
if (chessboard.moveCounter % 2 == 0) {
transaction.add(com.zlaporta.chessgame.R.id.game_play_screen, gameInfo, "InfoTest");
} else {
transaction.add(com.zlaporta.chessgame.R.id.game_play_black_screen, gameInfo, "InfoTestBlack");
}
transaction.commit();
Toolbar toolbar = (Toolbar) findViewById(R.id.app_bar);
toolbar.setTitle("Current Game");
setSupportActionBar(toolbar);
DBAdapter boardstateDB = new DBAdapter(chessboard.this);
boardstateDB.open();
Cursor cur = boardstateDB.getAllRows();
if (cur != null && cur.moveToFirst()) {
cur.moveToLast();
String pieceData = cur.getString(cur.getColumnIndex("piecepositions"));
whiteKingMoved = cur.getInt(cur.getColumnIndex("whitekingmoved"));
blackKingMoved = cur.getInt(cur.getColumnIndex("blackkingmoved"));
leftWRMoved = cur.getInt(cur.getColumnIndex("whiterook1moved"));
rightWRMoved = cur.getInt(cur.getColumnIndex("whiterook2moved"));
leftBRMoved = cur.getInt(cur.getColumnIndex("blackrook1moved"));
rightBRMoved = cur.getInt(cur.getColumnIndex("blackrook2moved"));
moveCounter = cur.getInt(cur.getColumnIndex("movecount"));
String madeMoves = cur.getString(cur.getColumnIndex("mademoves"));
storedTakenPieces = cur.getString(cur.getColumnIndex("takenpieces"));
SQLiteDataInterpreter boardRefresher = new SQLiteDataInterpreter();
boardRefresher.refreshBoard(pieceData, madeMoves, chessboard.this, storedTakenPieces);
} else {
boardstateDB.updateGameState("r00 k01 b02 q03 a04 b05 k06 r07 p10 p11 p12 p13 p14 p15 p16 p17 P60 P61 P62 P63 P64 P65 P66 P67 R70 K71 B72 Q73 A74 B75 K76 R77",
0, 0, 0, 0, 0, 0, 0, " ", " ");
Cursor curs = boardstateDB.getAllRows();
curs.moveToLast();
String pieceData = curs.getString(curs.getColumnIndex("piecepositions"));
whiteKingMoved = curs.getInt(curs.getColumnIndex("whitekingmoved"));
blackKingMoved = curs.getInt(curs.getColumnIndex("blackkingmoved"));
leftWRMoved = curs.getInt(curs.getColumnIndex("whiterook1moved"));
rightWRMoved = curs.getInt(curs.getColumnIndex("whiterook2moved"));
leftBRMoved = curs.getInt(curs.getColumnIndex("blackrook1moved"));
rightBRMoved = curs.getInt(curs.getColumnIndex("blackrook2moved"));
moveCounter = curs.getInt(curs.getColumnIndex("movecount"));
String madeMoves = curs.getString(curs.getColumnIndex("mademoves"));
storedTakenPieces = curs.getString(curs.getColumnIndex("takenpieces"));
SQLiteDataInterpreter boardRefresher = new SQLiteDataInterpreter();
boardRefresher.refreshBoard(pieceData, madeMoves, chessboard.this, storedTakenPieces);
And the relevant code in my GameInfoFragment class which is causing problems:
public void setTakenPiece(String[] takenpiecerecord) {
takenPiece = takenpiecerecord;
int c;
for (c = 0; c < takenPiece.length; c++) {
String takenPieceHolder = "t" + c;
String pieceCheck = takenPiece[c];
//System.out.println(square);
int takenPieceHolderID = this.getResources().getIdentifier(takenPieceHolder, "id", getActivity().getPackageName());
ImageView takenPieceHolderSquare = (ImageView) v.findViewById(takenPieceHolderID);
The main line of code that is causing issues is where I try to set the value of takenPieceHolderID in the code directly above.
How can I ensure that my fragment is added so that its imageViews will be populated upon the start of my Chessboard Activity?
You should check if Activity exists and if isAdded() is True
public void setTakenPiece(String[] takenpiecerecord) {
activity = getActivity();
if (isAdded() && activity) {
takenPiece = takenpiecerecord;
int c;
for (c = 0; c < takenPiece.length; c++) {
String takenPieceHolder = "t" + c;
String pieceCheck = takenPiece[c];
//System.out.println(square);
int takenPieceHolderID = this.getResources().getIdentifier(takenPieceHolder, "id", getActivity().getPackageName());
ImageView takenPieceHolderSquare = (ImageView) v.findViewById(takenPieceHolderID);
}}
I use the fragment manager to find the fragment by tag. If it returns null I have problems with fragment creation. This depends on whether my fragment has a valid container, calls an adapter and the adapter is unhappy, or if it calls a view improperly, so double check all. Make sure your container is added to your ViewGroup, if you are using one, and that the container is detached from any parent.
I create my fragments programatically and set tag names that can be searched.
Using debug, be sure that the fragment constructor is called, then make sure onCreateView is called. If so, single step through onCreateView and look for a line that bombs. Make sure the fragment returns a view.
Also be sure what type of fragment you are using, android or android.support.v4.app.Fragment.
At times I have had to use FragmentManager whatever_your_name_is.executePendingTransactions to ensure that the fragment has been added prior to being accessed. Be sure to use the fragment manager that launched the fragment.
That's my brain dump, good luck.

Categories

Resources