androidXP androidXP - 4 months ago 55
JSON Question

Android-RecyclerView Set Image And Text From JSON

Hi i am trying to make RecyclerView List From JSON which is sending Image URL and Name (Only these i need to display to RecyclerView For Now). I tried Google and Stack From past 2 days but Still No Solution To Set Text and Images From JSON to RecyclerView Most of the tutorials use Volley or Other Library and They use AsyncTask in Same Class (which solve data passing problem ). Which I am not using

I have successfully made recyclerView with local images and text Stored in Drawable Folder and In String Array(Values-->String.xml) and its working fine

But my condition is different then most of the solution

1) I am calling AsyncTask.Execute Method From Parent Activity of Fragment

2) My AsyncTask Class is not in same class where i am calling AsyncTask.Execute Method.

3) I am trying get values in Fragment from AsyncTask which always return Null even after setting setter and getter method (Hard time in transfer Images[] and Name[] to Fragment)

4) As i m getting Image Path in String[] then how to set path into Recycler View

Here is my Classes

***From Where I am Calling AsyncTask.Execute Method.

public class Navigation_Drawer extends AppCompatActivity {

@Override
public boolean onOptionsItemSelected(MenuItem item) {
//Handle Item Selection
switch (item.getItemId()){
case R.id.action_websearch:
Toast.makeText(getBaseContext(), "You have Clicked WebSearch", Toast.LENGTH_LONG).show();
break;
case R.id.parseJson:
new JsonParsing().execute();//AYSNCTASK EXECUTE
}


Then That Aysnctask Execute Called This Class

public class JsonParsing extends AsyncTask<String, Void, List<String[]>> {

private String URL_Path="http://www.example.com/test/Android/Data/showUers.php";
private static final String TAG="JSON PARSER******";
HttpURLConnection connection;
BufferedReader reader;
private Context context;



@Override
protected String[] doInBackground(String... params) {
try {
URL url=new URL(URL_Path);
connection= (HttpURLConnection) url.openConnection();
connection.connect();
Log.d(TAG,connection.toString());

InputStream inputStream=connection.getInputStream();
reader=new BufferedReader(new InputStreamReader(inputStream));
String line;
StringBuffer stringBuffer=new StringBuffer();
while ((line=reader.readLine())!=null){
stringBuffer.append(line);

}
String completeJSON=stringBuffer.toString();

JSONArray parentArray=new JSONArray(completeJSON);
String[] Name=new String[parentArray.length()];
String[] ImagePath=new String[parentArray.length()];
for (int i = 0; i <parentArray.length() ; i++) {
JSONObject childObject=parentArray.getJSONObject(i);

String Fname=childObject.getString("First_Name") ;
String Lname=childObject.getString("Last_Name") ;

Name[i]=Fname+" "+Lname;
ImagePath[i]=childObject.getString("Image");
Log.d(TAG,"String Arrays "+Name[i]+" "+ ImagePath[i]);
//THIS LOG SUCCESSFULLY SHOWING RESULT IN LOG


}

List<String[]> results=new ArrayList<>(2);
results.add(Name);
results.add(ImagePath);
return results;

} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
} finally {

try {
connection.disconnect();
if (reader!=null) {
reader.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}

return null;
}





@Override
protected void onPostExecute(List<String[]> results) {
Log.d(TAG,"ON POST EXECUTE CALLING START");
String[] Name=results.get(0);
String[] Image=results.get(1);
Log.d(TAG,"ON POST EXECUTE CALLING Bundle");
FriendsList friendsListFragment=new FriendsList();
Bundle dataToPass=new Bundle();
dataToPass.putStringArray("Names",Name);
dataToPass.putStringArray("ImagePath",Image);
friendsListFragment.setArguments(dataToPass);
friendsListFragment.getData(dataToPass);
Log.d(TAG,"ON POST EXECUTE CALLING LAST "+Name.toString());

}


And This Is My Fragment Where I am Calling RecyclerView

public class FriendsList extends Fragment {

RecyclerView recyclerView;
RecyclerView.Adapter adapter;
RecyclerView.LayoutManager layoutManager;
TypedArray Image;

public static final String TAG="Friends List******";

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view=inflater.inflate(R.layout.activity_friend_list,container,false);
recyclerView= (RecyclerView) view.findViewById(R.id.RecyclerViewForFriendList);

Name=getResources().getStringArray(R.array.left_Drawer_Menu);
Image=getResources().obtainTypedArray(R.array.user_image);

recyclerView.setHasFixedSize(true);
adapter=new RecyclerFriendListAdapter(getActivity(),Name,Image);
recyclerView.setAdapter(adapter);
recyclerView.setAdapter(adapter);
layoutManager=new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);


String[] Name=getArguments().getStringArray("Names");//Returns Null
String[] Image=getArguments().getStringArray("ImagePath");

return view;
}



public void getData(Bundle savedInstanceState){
if (savedInstanceState!=null) {
Log.d(TAG, "GET DATA CALLING ");
String[] New_Name = getArguments().getStringArray("Names");
String[] New_ImagePath =getArguments().getStringArray("ImagePath");
Log.d(TAG, "ON CREATE SETTING NAME AND IMAGEPATH INTO ARRAY " + New_ImagePath[2]+" "+New_Name[1]);
adapter=new RecyclerFriendListAdapter(getActivity(),New_Name,New_ImagePath);
recyclerView.setAdapter(adapter);//*************RETURNS NULL
Log.d(TAG, "GET DATA CALLING FINISHED ");


}
}}


Recycler Adapter CLass

public class RecyclerFriendListAdapter extends RecyclerView.Adapter<RecyclerFriendListAdapter.ViewHolder> {
String[] Name,ImagePath;
TypedArray Image;
Context context;
static final String TAG="FRIEND LIST ADAPTER****";


public RecyclerFriendListAdapter(Context context,String[] name,TypedArray image) {
this.context = context;
Image = image;
Name = name;
}

public RecyclerFriendListAdapter(Context context,String[] image, String[] name) {
this.context=context;
ImagePath = image;
Name = name;
}


@Override
public RecyclerFriendListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater= (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view=layoutInflater.inflate(R.layout.listview_item_recycler,null);
Log.d(TAG,"Constructor Calling");
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(RecyclerFriendListAdapter.ViewHolder holder, int position) {
Log.d(TAG,"Holder "+position);
holder.UserImage.setImageResource(Image.getResourceId(position,0));
holder.Name.setText(Name[position]);
}

@Override
public int getItemCount() {
return Name.length;
}

public static class ViewHolder extends RecyclerView.ViewHolder {
TextView Name;
ImageView UserImage;
Context context;

public ViewHolder(View v) {
super(v);
Log.d(TAG,"View Holder");

Name= (TextView) v.findViewById(R.id.User_Name_Item);
UserImage= (ImageView) v.findViewById(R.id.UserImage);
}


}


I know i am doing some mistakes in code But I need to do These things

Get Images And Names String Array from doinbackground then get these Values in Fragment and send both array to RecyclerView Adapter to show in recyclerview List.

Its Little Advance Question and only Experts can solve this so please help me resolve this issue

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
new JsonParsing.execute();
showSkipButton(true);
setProgressButtonEnabled(true);

}


@Override
public void onDonePressed(Fragment currentFragment) {
super.onDonePressed(currentFragment);
Intent intent=new Intent(this,Parent_Activty.class);
startActivity(intent);
}


And This Is Parent Activity Where Fragment is Attached

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.parent_layout);

//First set up toolbar
setupToolbar();

//Add the Fragment to the container
FragmentTransaction transaction=getFragmentManager().beginTransaction();
FriendsList friendList=new FriendsList();
transaction.replace(R.id.Parent_Main_Layout,friendList);
transaction.commit();
}


New Interface As @Cricket_007 Suggest and Wrapper Class

public interface onResultReceived {
public void onResultRececivedFuc(List<String[]> users);
}


Wrapper Class

public class WrapperClass {

String[] Name,Image;

public String[] getName() {
return Name;
}

public void setName(String[] name) {
Name = name;
}

public String[] getImage() {
return Image;
}

public void setImage(String[] image) {
Image = image;
}

}


And At Last My Log

08-07 02:17:57.490 32184-32184/com.recyclerview_pro_working1 D/Friends List******: ON CREATE CALLING
08-07 02:17:57.490 32184-32184/com.recyclerview_pro_working1 D/Friends List******: ON CREATE VIEW START
08-07 02:17:57.490 32184-32184/com.recyclerview_pro_working1 D/Friends List******: PUTTING VALUE INTO NAME AND IMAGE
08-07 02:17:57.490 32184-32184/com.recyclerview_pro_working1 D/Friends List******: ON CREATE VIEW [Ljava.lang.String;@437092e0
08-07 02:17:57.550 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.550 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.550 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 0
08-07 02:17:57.600 32184-32188/com.recyclerview_pro_working1 D/dalvikvm: GC_CONCURRENT freed 1791K, 42% free 24608K/41927K, paused 2ms+3ms, total 33ms
08-07 02:17:57.600 32184-32184/com.recyclerview_pro_working1 D/dalvikvm: WAIT_FOR_CONCURRENT_GC blocked 17ms
08-07 02:17:57.640 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.640 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.640 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 1
08-07 02:17:57.650 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.650 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.650 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 2
08-07 02:17:57.660 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.660 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.660 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 3
08-07 02:17:57.670 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.670 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.670 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 4
08-07 02:17:57.680 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.680 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.680 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 5
08-07 02:17:57.680 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Constructor Calling
08-07 02:17:57.680 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: View Holder
08-07 02:17:57.690 32184-32184/com.recyclerview_pro_working1 D/FRIEND LIST ADAPTER****: Holder 6
08-07 02:17:57.700 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position0
08-07 02:17:57.700 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position1
08-07 02:17:57.710 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position2
08-07 02:17:57.720 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position3
08-07 02:17:57.720 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position4
08-07 02:17:57.730 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position5
08-07 02:17:57.730 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position6
08-07 02:17:57.740 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position7
08-07 02:17:57.740 32184-32184/com.recyclerview_pro_working1 D/ADAPTER*********: Value of Position8
08-07 02:18:19.830 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: DO IN BACKGROUND START
08-07 02:18:20.580 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: libcore.net.http.HttpURLConnectionImpl:DOMAIN NAME/test/Android/Data/showUers.php
08-07 02:18:21.200 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: GET INPUT STREAM AND PUUTING INTO READER
08-07 02:18:21.200 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: JSON ARRAY START
08-07 02:18:21.210 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: String Arrays Julien Blin DOMAIN NAME/test/Android/Data/uploads/Julien.jpg
08-07 02:18:21.210 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: String Arrays Iveta Benesova DOMAIN NAME/test/Android/Data/uploads/Iveta.jpg
08-07 02:18:21.210 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: String Arrays Varun Razora DOMAIN NAME/test/Android/Data/uploads/Varun.jpg
08-07 02:18:21.210 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: JSON PARSING FINISHED
08-07 02:18:21.210 32184-3367/com.recyclerview_pro_working1 D/JSON PARSER******: Return Statement
08-07 02:18:21.210 32184-32184/com.recyclerview_pro_working1 D/JSON PARSER******: ON POST EXECUTE CALLING START
08-07 02:18:21.210 32184-32184/com.recyclerview_pro_working1 D/JSON PARSER******: ON POST EXECUTE CALLING STOP
08-07 02:18:21.210 32184-32184/com.recyclerview_pro_working1 D/Friends List******: GET DATA CALLING
08-07 02:18:21.210 32184-32184/com.recyclerview_pro_working1 D/Friends List******: ON CREATE SETTING NAME AND IMAGEPATH INTO ARRAY DOMAIN NAME/test/Android/Data/uploads/Varun.jpg Iveta Benesova
08-07 02:18:21.210 32184-32184/com.recyclerview_pro_working1 D/AndroidRuntime: Shutting down VM
08-07 02:18:21.210 32184-32184/com.recyclerview_pro_working1 W/dalvikvm: threadid=1: thread exiting with uncaught exception (group=0x416dd378)
08-07 02:18:21.220 32184-32184/com.recyclerview_pro_working1 E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.NullPointerException
at com.recyclerview_pro_working1.mainScreenFragments.FriendsList.getData(FriendsList.java:99)
at com.recyclerview_pro_working1.Sending_Image_To_Server.onPostExecute(Sending_Image_To_Server.java:130)
at com.recyclerview_pro_working1.Sending_Image_To_Server.onPostExecute(Sending_Image_To_Server.java:29)
at android.os.AsyncTask.finish(AsyncTask.java:631)
at android.os.AsyncTask.access$600(AsyncTask.java:177)
at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:213)
at android.app.ActivityThread.main(ActivityThread.java:4787)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:789)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:556)
at dalvik.system.NativeStart.main(Native Method)


EDIT #1 As @Hendra Wijaya Djiono Suggest I edit my code And Its Returns Null Still and I think its more cause of fragment launch when there is no value (I am calling AsyncTask before too) where i start Parent Activity Like This

EDIT #2 As both @Hendra Wijaya Djiono and @cricket_007 suggest both answers work as i expect but @Hendra Bundle Point seems easy and clear and @cricket_007 code suggest avoid bundle i agree with him that bundle would be null when Fragment is created but just for app to work i updated log and code its sending data to fragment via bundle successfully but its comes with 2 more problems first as you can see recyclerview.setAdapter(adapter) throws null pointer and how can i set imagePath(URL of Image) to ImageView In adapter.

EDIT #3 @Cricket_007 Suggested I added Interface and Wrapper Class but putting both string (Name[] and Image[]) Into List List=new ArrayList(); gives me hard time.So i used Noraml List Function and put both string into it then get it into onPostExecute.

Answer

To address the update

getActivity has returned you null when you declare the adapter because you made an completely new, empty Fragment, didn't attach it to an Activity.

Then, the second issue is you pass a new Bundle into the getData method, but you don't even use that savedInstanceState parameter, you instead used getArguments. Overall, as written below, stop using Fragment Bundle arguments


Firstly, make a class to parse your JSON into. You can use Gson or Jackson if you want to simplify that process, but encapsulating these String[]'s into a List of objects will make the process easier. And addresses returning multiple String[] in the AsyncTask.

public class User {
    private String name;
    private String imageUrl;
    // getters, setters, etc.
}

Secondly, (following How to get the result of OnPostExecute() ... because AsyncTask is a separate class?) you can define an interface to "call back" to the UI thread with your list of results.

public interface AsyncUserResponse {
    public void onUsersReceived(List<User> users);
}

Next, you want your AsyncTask to return you a List<User>, and you aren't using the String parameters, so you can make that Void.

public class GetUsersTask extends AsyncTask<Void, Void, List<User>> {

    private AsyncUserResponse delegate;
    public GetUsersTask(AsyncUserResponse delegate) {
        this.delegate = delegate;
    }    

    public List<User> doInBackground(Void... params) {
        List<User> users = new ArraryList<User>();
        // TODO: HTTP Request

        // TODO: Parse JSON string - store into list
        // Loop over some JSON array 
            String name = json.get("name");
            String image = json.get("image_url");
            User u = new User(name, image);
            users.add(u);
        // End loop 
        return users;
    }

    public void onPostExecute(List<User> result) {
        if (delegate != null) {
            delegate.onUsersReceived(result);
        } 
        // nothing else goes here - this method is done 
    }
}

Finally, in order to call that AsyncTask in your Fragment class and get back your results to your adapter, your class can implement that interface, or you can in-line an anonymous class. Your choice.

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view=inflater.inflate(R.layout.activity_friend_list,container,false);

    recyclerView= (RecyclerView) view.findViewById(R.id.RecyclerViewForFriendList);
    recyclerView.setHasFixedSize(true);
    layoutManager=new LinearLayoutManager(getActivity());
    recyclerView.setLayoutManager(layoutManager);

    AsyncUserResponse listener = new AsyncUserResponse() {
        @Override
        public void onUsersReceived(List<User> users) {
            adapter=new RecyclerFriendListAdapter(getActivity(), users);
            recyclerView.setAdapter(adapter);
        }
    };

    new GetUsersTask(listener).execute();


    return view;
}

Note: You'll additionally need to modify the adapter to take a List<User> instead of two String arrays.

Take away here -- Forget the bundle arguments. You are running asynchronous code, so you won't have arguments to get when the Fragment's View is created. This is the same pattern used by Volley, OkHttp, Retrofit, etc. And it is good to understand how they work.